Skip to content

Commit

Permalink
avm1: Make clip have correct properties when the target of loadClip
Browse files Browse the repository at this point in the history
  • Loading branch information
colin969 committed May 4, 2024
1 parent 961b0bc commit 43fcd4e
Show file tree
Hide file tree
Showing 17 changed files with 103 additions and 15 deletions.
52 changes: 52 additions & 0 deletions core/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::vminterface::Instantiator;
use crate::{avm2_stub_method, avm2_stub_method_context};
use encoding_rs::UTF_8;
use gc_arena::{Collect, GcCell};
use indexmap::IndexMap;
use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
use slotmap::{new_key_type, SlotMap};
use std::borrow::Borrow;
Expand Down Expand Up @@ -1004,6 +1005,21 @@ impl<'gc> Loader<'gc> {
if let Some(mut mc) = clip.as_movie_clip() {
if !mc.movie().is_action_script_3() {
mc.avm1_unload(uc);

// Clear deletable properties on the target before loading
// Properties written during the subsequent onLoad events will persist
let clip_value = mc.object();
if let Value::Object(clip_object) = clip_value {
let mut activation = Activation::from_nothing(
uc.reborrow(),
ActivationIdentifier::root("unknown"),
clip,
);

for key in clip_object.get_keys(&mut activation, true) {
clip_object.delete(&mut activation, key);
}
}
}

// Before the actual SWF is loaded, an initial loading state is entered.
Expand All @@ -1019,7 +1035,43 @@ impl<'gc> Loader<'gc> {

let movie = SwfMovie::from_data(&body, url.to_string(), loader_url)?;
player.lock().unwrap().mutate_with_update_context(|uc| {
// Make a copy of the properties on the root, so we can put them back after replacing it
let mut root_properties: IndexMap<AvmString, Value> = IndexMap::new();
if let Some(root) = uc.stage.root_clip() {
let root_val = root.object();
if let Value::Object(root_object) = root_val {
let mut activation = Activation::from_nothing(
uc.reborrow(),
ActivationIdentifier::root("unknown"),
root,
);
for key in root_object.get_keys(&mut activation, true) {
let val = root_object
.get_stored(key, &mut activation)
.unwrap_or(Value::Undefined);
root_properties.insert(key, val);
}
}
}

uc.replace_root_movie(movie);

// Add the copied properties back onto the new root
if !root_properties.is_empty() {
if let Some(root) = uc.stage.root_clip() {
let val = root.object();
if let Value::Object(clip_object) = val {
let mut activation = Activation::from_nothing(
uc.reborrow(),
ActivationIdentifier::root("unknown"),
root,
);
for (key, val) in root_properties {
let _ = clip_object.set(key, val, &mut activation);
}
}
}
}
});
return Ok(());
}
Expand Down
5 changes: 0 additions & 5 deletions tests/tests/swfs/avm1/mcl_loadclip_onload_target/child.as

This file was deleted.

3 changes: 0 additions & 3 deletions tests/tests/swfs/avm1/mcl_loadclip_onload_target/output.txt

This file was deleted.

Binary file not shown.
2 changes: 0 additions & 2 deletions tests/tests/swfs/avm1/mcl_loadclip_onload_target/test.toml

This file was deleted.

3 changes: 3 additions & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_properties/child.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Child {
static function main() {}
}
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_properties/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
onLoadStart
undefined
onLoadComplete
message from onLoadStart
onLoadInit
message from onLoadComplete
30 changes: 30 additions & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_properties/test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Test {
static function main() {
var loader = new MovieClipLoader();
var mc = _root.createEmptyMovieClip("child.swf", 1);
mc.message = "Original Message";

var o = new Object();

o.onLoadInit = function(target) {
trace("onLoadInit");
trace(target.message);
target.message = "message from onLoadInit"
}

o.onLoadStart = function(target) {
trace("onLoadStart");
trace(target.message);
target.message = "message from onLoadStart"
}

o.onLoadComplete = function(target) {
trace("onLoadComplete");
trace(target.message);
target.message = "message from onLoadComplete"
}

loader.addListener(o);
loader.loadClip("child.swf", mc);
}
}
Binary file not shown.
1 change: 1 addition & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_properties/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 2
5 changes: 5 additions & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_replace_root/child.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Child {
static function main() {
trace(_root.message); // message from onLoadStart
}
}
1 change: 1 addition & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_replace_root/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
message from onLoadStart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ class Test {
var loader = new MovieClipLoader();

var o = new Object();

o.onLoadStart = function(target) {
trace(target.message); // load
_root.message = "Target Message";
trace(target.message);
};
target.message = "message from onLoadStart"
}

loader.addListener(o);
loader.loadClip("child.swf", "_level0");
}
}
}
Binary file not shown.
1 change: 1 addition & 0 deletions tests/tests/swfs/avm1/mcl_loadclip_replace_root/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 2

0 comments on commit 43fcd4e

Please sign in to comment.