avm1: Fix `loadVariablesNum` / `Action::GetUrl2`

This commit is contained in:
Toad06 2022-02-23 20:22:16 +01:00 committed by Mike Welsh
parent badb91c1db
commit 055e1d4dc1
1 changed files with 82 additions and 64 deletions

View File

@ -1190,50 +1190,81 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
fn action_get_url_2(&mut self, action: GetUrl2) -> Result<FrameControl<'gc>, Error<'gc>> { fn action_get_url_2(&mut self, action: GetUrl2) -> Result<FrameControl<'gc>, Error<'gc>> {
// TODO: Support `LoadVariablesFlag`, `LoadTargetFlag` // TODO: Support `LoadVariablesFlag`, `LoadTargetFlag`
// TODO: What happens if there's only one string? // TODO: What happens if there's only one string?
let target = self.context.avm1.pop(); let target_val = self.context.avm1.pop();
let target = target_val.coerce_to_string(self)?;
let url_val = self.context.avm1.pop(); let url_val = self.context.avm1.pop();
let url = url_val.coerce_to_string(self)?; let url = url_val.coerce_to_string(self)?;
if let Some(fscommand) = fscommand::parse(&url) { if let Some(fscommand) = fscommand::parse(&url) {
let fsargs = target.coerce_to_string(self)?; // `target` = fscommand arguments!
fscommand::handle(fscommand, &fsargs, self)?; fscommand::handle(fscommand, &target, self)?;
return Ok(FrameControl::Continue); return Ok(FrameControl::Continue);
} }
let window_target = target.coerce_to_string(self)?; // TODO: Use `StageObject::get_level_by_path`.
let clip_target: Option<DisplayObject<'gc>> = if action.is_target_sprite() { let level_target = if target.starts_with(WStr::from_units(b"_level")) && target.len() >= 6 {
if let Value::Object(target) = target { match target[6..].parse::<f64>() {
Ok(level_id) => level_id as i32,
Err(_) => {
if target.len() == 6 {
0
} else {
-1
}
}
}
} else {
-1
};
let clip_target: Option<DisplayObject<'gc>> = if level_target > -1 {
Some(self.resolve_level(level_target))
} else if action.is_load_vars() || action.is_target_sprite() {
if let Value::Object(target) = target_val {
target.as_display_object() target.as_display_object()
} else { } else {
let start = self.target_clip_or_root(); let start = self.target_clip_or_root();
self.resolve_target_display_object(start, target, true)? self.resolve_target_display_object(start, target_val, true)?
} }
} else { } else {
Some(self.target_clip_or_root()) None
}; };
if action.is_load_vars() { if action.is_load_vars() {
if let Some(clip_target) = clip_target { // `loadVariables` or `loadVariablesNum` call.
let target_obj = clip_target // Depending on the situation, it will open a link in the browser instead.
.as_movie_clip() let mut is_load_vars = true;
.unwrap() if !(action.is_target_sprite() || level_target > -1) {
.object() is_load_vars = false;
.coerce_to_object(self); if matches!(target_val, Value::Object(_)) {
let (url, opts) = self.locals_into_request_options( if let Some(clip) = clip_target {
&url, is_load_vars = DisplayObject::ptr_eq(clip, self.base_clip().avm1_root());
NavigationMethod::from_send_vars_method(action.send_vars_method()), }
); }
let future = self.context.load_manager.load_form_into_object( }
self.context.player.clone().unwrap(), if is_load_vars {
target_obj, if let Some(clip_target) = clip_target {
&url, let target_obj = clip_target
opts, .as_movie_clip()
); .unwrap()
self.context.navigator.spawn_future(future); .object()
.coerce_to_object(self);
let (url, opts) = self.locals_into_request_options(
&url,
NavigationMethod::from_send_vars_method(action.send_vars_method()),
);
let future = self.context.load_manager.load_form_into_object(
self.context.player.clone().unwrap(),
target_obj,
&url,
opts,
);
self.context.navigator.spawn_future(future);
}
return Ok(FrameControl::Continue);
} }
return Ok(FrameControl::Continue);
} else if action.is_target_sprite() { } else if action.is_target_sprite() {
// `loadMovie`, `unloadMovie` or `unloadMovieNum` call.
if let Some(clip_target) = clip_target { if let Some(clip_target) = clip_target {
let (url, opts) = self.locals_into_request_options( let (url, opts) = self.locals_into_request_options(
&url, &url,
@ -1241,7 +1272,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
); );
if url.is_empty() { if url.is_empty() {
//Blank URL on movie loads = unload! // Blank URL on movie loads = unload!
if let Some(mut mc) = clip_target.as_movie_clip() { if let Some(mut mc) = clip_target.as_movie_clip() {
mc.replace_with_movie(self.context.gc_context, None) mc.replace_with_movie(self.context.gc_context, None)
} }
@ -1258,45 +1289,32 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
} }
} }
return Ok(FrameControl::Continue); return Ok(FrameControl::Continue);
} else if window_target.starts_with(WStr::from_units(b"_level")) && window_target.len() > 6 } else if level_target > -1 {
{ // `loadMovieNum` call.
// TODO: Use `StageObject::get_level_by_path`. if let Some(clip_target) = clip_target {
// target of `_level#` indicates a `loadMovieNum` call. let future = self.context.load_manager.load_movie_into_clip(
match window_target[6..].parse::<i32>() { self.context.player.clone().unwrap(),
Ok(level_id) => { clip_target,
let level = self.resolve_level(level_id); &url.to_utf8_lossy(),
RequestOptions::get(),
let future = self.context.load_manager.load_movie_into_clip( None,
self.context.player.clone().unwrap(), None,
level, );
&url.to_utf8_lossy(), self.context.navigator.spawn_future(future);
RequestOptions::get(),
None,
None,
);
self.context.navigator.spawn_future(future);
}
Err(e) => avm_warn!(
self,
"Couldn't parse level id {} for action_get_url_2: {}",
url,
e
),
} }
return Ok(FrameControl::Continue); return Ok(FrameControl::Continue);
} else {
let vars = match NavigationMethod::from_send_vars_method(action.send_vars_method()) {
Some(method) => Some((method, self.locals_into_form_values())),
None => None,
};
self.context.navigator.navigate_to_url(
url.to_string(),
Some(window_target.to_string()),
vars,
);
} }
// `getURL` call.
let vars = match NavigationMethod::from_send_vars_method(action.send_vars_method()) {
Some(method) => Some((method, self.locals_into_form_values())),
None => None,
};
self.context
.navigator
.navigate_to_url(url.to_string(), Some(target.to_string()), vars);
Ok(FrameControl::Continue) Ok(FrameControl::Continue)
} }