Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/src/avm2/globals/flash/display/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,11 @@ pub fn get_loader_info<'gc>(
{
return Ok(loader_info.into());
}

if let Some(loader_info_obj) = dobj.loader_info() {
return Ok(loader_info_obj.into());
}

return Ok(Value::Null);
}
Ok(Value::Undefined)
Expand Down
25 changes: 21 additions & 4 deletions core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ pub struct DisplayObjectBase<'gc> {
/// None means not cached, Some means cached.
#[collect(require_static)]
cache: Option<BitmapCache>,

/// Loader info.
loader_info: Option<Avm2Object<'gc>>,
}

impl Default for DisplayObjectBase<'_> {
Expand Down Expand Up @@ -281,6 +284,7 @@ impl Default for DisplayObjectBase<'_> {
next_scroll_rect: Cell::new(Default::default()),
scaling_grid: Cell::new(Default::default()),
cache: None,
loader_info: None,
}
}
}
Expand Down Expand Up @@ -801,6 +805,14 @@ impl<'gc> DisplayObjectBase<'gc> {
pub fn set_has_matrix3d_stub(&self, value: bool) {
self.set_flag(DisplayObjectFlags::HAS_MATRIX3D_STUB, value)
}

pub fn loader_info(&self) -> Option<Avm2Object<'gc>> {
self.loader_info
}

pub fn set_loader_info(&mut self, loader_info: Avm2Object<'gc>) {
self.loader_info = Some(loader_info);
}
}

struct DrawCacheInfo {
Expand Down Expand Up @@ -1970,6 +1982,15 @@ pub trait TDisplayObject<'gc>:
fn set_has_explicit_name(self, value: bool) {
self.base().set_has_explicit_name(value);
}

fn loader_info(self) -> Option<Avm2Object<'gc>> {
self.base().loader_info()
}

fn set_loader_info(self, gc_context: &Mutation<'gc>, loader_info: Avm2Object<'gc>) {
self.base_mut(gc_context).set_loader_info(loader_info);
}

fn state(&self) -> Option<ButtonState> {
None
}
Expand Down Expand Up @@ -2348,10 +2369,6 @@ pub trait TDisplayObject<'gc>:
/// Return the SWF that defines this display object.
fn movie(self) -> Arc<SwfMovie>;

fn loader_info(self) -> Option<Avm2Object<'gc>> {
None
}

fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc>;

fn as_ptr(self) -> *const DisplayObjectPtr;
Expand Down
29 changes: 28 additions & 1 deletion core/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::avm2::object::{
LoaderStream, SoundLoadingState, TObject as _,
};
use crate::avm2::{
Activation as Avm2Activation, Avm2, BitmapDataObject, Domain as Avm2Domain,
self, Activation as Avm2Activation, Avm2, BitmapDataObject, Domain as Avm2Domain,
Object as Avm2Object,
};
use crate::avm2_stub_method_context;
Expand Down Expand Up @@ -2467,6 +2467,33 @@ impl<'gc> Loader<'gc> {
);

loader_info.set_expose_content();
if let Some(_dobj) = dobj {
let mut activation = Avm2Activation::from_nothing(uc);
let loader_stream = loader_info.loader_stream();
let loader_content_object = match &*loader_stream {
LoaderStream::Swf(_, root) | LoaderStream::NotYetLoaded(_, Some(root), _) => {
if root.movie().is_action_script_3() || !root.movie().is_movie() {
root.object2()
} else {
// The movie was an AVM1 movie, return an AVM1Movie object
let root_obj = *root;
drop(loader_stream);

loader_info
.get_or_init_avm1movie(&mut activation, root_obj)
.into()
}
}
_ => avm2::Value::Null,
};

loader_content_object
.as_object()
.unwrap()
.as_display_object()
.unwrap()
.set_loader_info(activation.gc(), loader_info.into());
}

// Note that we do *not* use the 'addChild' method here:
// Per the flash docs, our implementation always throws
Expand Down