avm1: Move root_object, target_clip_or_root, target_clip and base_clip from avm1 to StackFrame

This commit is contained in:
Nathan Adams 2020-06-28 15:39:49 +02:00
parent ca305684db
commit d470c52aea
6 changed files with 56 additions and 59 deletions

View File

@ -136,31 +136,6 @@ impl<'gc> Avm1<'gc> {
}
}
#[allow(dead_code)]
pub fn base_clip(&self) -> DisplayObject<'gc> {
self.current_stack_frame().unwrap().read().base_clip()
}
/// The current target clip for the executing code.
/// This is the movie clip that contains the bytecode.
/// Timeline actions like `GotoFrame` use this because
/// a goto after an invalid tellTarget has no effect.
pub fn target_clip(&self) -> Option<DisplayObject<'gc>> {
self.current_stack_frame().unwrap().read().target_clip()
}
/// The current target clip of the executing code, or `root` if there is none.
/// Actions that affect `root` after an invalid `tellTarget` will use this.
///
/// The `root` is determined relative to the base clip that defined the
pub fn target_clip_or_root(&self) -> DisplayObject<'gc> {
self.current_stack_frame()
.unwrap()
.read()
.target_clip()
.unwrap_or_else(|| self.base_clip().root())
}
/// Add a stack frame that executes code in timeline scope
pub fn run_stack_frame_for_action(
&mut self,
@ -473,11 +448,6 @@ impl<'gc> Avm1<'gc> {
value
}
/// Obtain the value of `_root`.
pub fn root_object(&self, _context: &mut UpdateContext<'_, 'gc, '_>) -> Value<'gc> {
self.base_clip().root().object()
}
/// Obtain the value of `_global`.
pub fn global_object(&self, _context: &mut UpdateContext<'_, 'gc, '_>) -> Value<'gc> {
Value::Object(self.globals)

View File

@ -86,7 +86,7 @@ fn target<'gc>(
let target = this.get("target", activation, context)?;
// Undefined or empty target is no-op.
if target != Value::Undefined && !matches!(&target, &Value::String(ref s) if s.is_empty()) {
let start_clip = activation.avm().target_clip_or_root();
let start_clip = activation.target_clip_or_root();
activation.resolve_target_display_object(context, start_clip, target)
} else {
Ok(None)

View File

@ -66,7 +66,7 @@ pub fn define_display_object_proto<'gc>(
gc_context,
"_root",
Executable::Native(|activation, context, _this, _args| {
Ok(activation.avm().root_object(context).into())
Ok(activation.root_object(context).into())
}),
Some(Executable::Native(overwrite_root)),
DontDelete | ReadOnly | DontEnum,

View File

@ -514,7 +514,7 @@ fn create_empty_movie_clip<'gc>(
// Create empty movie clip.
let swf_movie = movie_clip
.movie()
.or_else(|| activation.avm().base_clip().movie())
.or_else(|| activation.base_clip().movie())
.unwrap();
let mut new_clip = MovieClip::new(SwfSlice::empty(swf_movie), context.gc_context);
@ -533,7 +533,7 @@ fn create_text_field<'gc>(
context: &mut UpdateContext<'_, 'gc, '_>,
args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
let movie = activation.avm().base_clip().movie().unwrap();
let movie = activation.base_clip().movie().unwrap();
let instance_name = args.get(0).cloned().unwrap_or(Value::Undefined);
let depth = args
.get(1)

View File

@ -824,7 +824,7 @@ pub fn xml_load<'gc>(
this.set("loaded", false.into(), activation, ac)?;
let fetch = ac.navigator.fetch(&url, RequestOptions::get());
let target_clip = activation.avm().target_clip_or_root();
let target_clip = activation.target_clip_or_root();
let process = ac.load_manager.load_xml_into_node(
ac.player.clone().unwrap(),
node,

View File

@ -327,7 +327,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let depth = self.avm.pop();
let target = self.avm.pop();
let source = self.avm.pop();
let start_clip = self.avm.target_clip_or_root();
let start_clip = self.target_clip_or_root();
let source_clip = self.resolve_target_display_object(context, start_clip, source)?;
if let Some(movie_clip) = source_clip.and_then(|o| o.as_movie_clip()) {
@ -417,7 +417,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
) -> Result<FrameControl<'gc>, Error<'gc>> {
// Runs any actions on the given frame.
let frame = self.avm.pop();
let clip = self.avm.target_clip_or_root();
let clip = self.target_clip_or_root();
if let Some(clip) = clip.as_movie_clip() {
// Use frame # if parameter is a number, otherwise cast to string and check for frame labels.
let frame = if let Value::Number(frame) = frame {
@ -435,7 +435,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
if let Some(frame) = frame {
for action in clip.actions_on_frame(context, frame) {
self.avm.run_stack_frame_for_action(
self.avm.target_clip_or_root(),
self.target_clip_or_root(),
self.avm.current_swf_version(),
action,
context,
@ -467,7 +467,6 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
.resolve(self, context)?;
let this = self
.avm
.target_clip_or_root()
.object()
.coerce_to_object(self, context);
@ -493,7 +492,6 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
match method_name {
Value::Undefined | Value::Null => {
let this = self
.avm
.target_clip_or_root()
.object()
.coerce_to_object(self, context);
@ -585,7 +583,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
params,
scope,
constant_pool,
self.avm.target_clip_or_root(),
self.target_clip_or_root(),
);
let prototype =
ScriptObject::object(context.gc_context, Some(self.avm.prototypes.object)).into();
@ -627,7 +625,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
action_func,
scope,
constant_pool,
self.avm.base_clip(),
self.base_clip(),
);
let prototype =
ScriptObject::object(context.gc_context, Some(self.avm.prototypes.object)).into();
@ -877,7 +875,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
) -> Result<FrameControl<'gc>, Error<'gc>> {
let prop_index = self.avm.pop().into_number_v1() as usize;
let path = self.avm.pop();
let ret = if let Some(target) = self.avm.target_clip() {
let ret = if let Some(target) = self.target_clip() {
if let Some(clip) = self.resolve_target_display_object(context, target, path)? {
let display_properties = self.avm.display_properties;
let props = display_properties.write(context.gc_context);
@ -985,11 +983,11 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
if let Value::Object(target) = target {
target.as_display_object()
} else {
let start = self.avm.target_clip_or_root();
let start = self.target_clip_or_root();
self.resolve_target_display_object(context, start, target.clone())?
}
} else {
Some(self.avm.target_clip_or_root())
Some(self.target_clip_or_root())
};
if is_load_vars {
@ -1054,7 +1052,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
frame: u16,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
// The frame on the stack is 0-based, not 1-based.
clip.goto_frame(self.avm, context, frame + 1, true);
@ -1075,7 +1073,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
) -> Result<FrameControl<'gc>, Error<'gc>> {
// Version 4+ gotoAndPlay/gotoAndStop
// Param can either be a frame number or a frame label.
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
let frame = self.avm.pop();
let _ = globals::movie_clip::goto_frame(
@ -1100,7 +1098,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
label: &str,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
if let Some(frame) = clip.frame_label_to_number(label) {
clip.goto_frame(self.avm, context, frame, true);
@ -1348,7 +1346,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
clip.next_frame(self.avm, context);
} else {
@ -1477,7 +1475,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
clip.play(context)
} else {
@ -1493,7 +1491,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
clip.prev_frame(self.avm, context);
} else {
@ -1584,7 +1582,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
let target = self.avm.pop();
let start_clip = self.avm.target_clip_or_root();
let start_clip = self.target_clip_or_root();
let target_clip = self.resolve_target_display_object(context, start_clip, target)?;
if let Some(target_clip) = target_clip.and_then(|o| o.as_movie_clip()) {
@ -1622,7 +1620,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let value = self.avm.pop();
let prop_index = self.avm.pop().coerce_to_u32(self, context)? as usize;
let path = self.avm.pop();
if let Some(target) = self.avm.target_clip() {
if let Some(target) = self.target_clip() {
if let Some(clip) = self.resolve_target_display_object(context, target, path)? {
let display_properties = self.avm.display_properties;
let props = display_properties.read();
@ -1668,7 +1666,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
target: &str,
) -> Result<FrameControl<'gc>, Error<'gc>> {
let base_clip = self.avm.base_clip();
let base_clip = self.base_clip();
let new_target_clip;
let root = base_clip.root();
let start = base_clip.object().coerce_to_object(self, context);
@ -1765,7 +1763,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
let target = self.avm.pop();
let start_clip = self.avm.target_clip_or_root();
let start_clip = self.target_clip_or_root();
let display_object = self.resolve_target_display_object(context, start_clip, target)?;
if let Some(display_object) = display_object {
let lock_center = self.avm.pop();
@ -1794,7 +1792,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.avm.target_clip() {
if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() {
clip.stop(context);
} else {
@ -2407,7 +2405,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
path: &'s str,
) -> Result<ReturnValue<'gc>, Error<'gc>> {
// Resolve a variable path for a GetVariable action.
let start = self.avm().target_clip_or_root();
let start = self.target_clip_or_root();
// Find the right-most : or . in the path.
// If we have one, we must resolve as a target path.
@ -2493,7 +2491,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
// Resolve a variable path for a GetVariable action.
let start = self.avm().target_clip_or_root();
let start = self.target_clip_or_root();
// If the target clip is invalid, we default to root for the variable path.
if path.is_empty() {
@ -2551,7 +2549,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
*level
} else {
let mut level: DisplayObject<'_> = MovieClip::new(
SwfSlice::empty(self.avm().base_clip().movie().unwrap()),
SwfSlice::empty(self.base_clip().movie().unwrap()),
context.gc_context,
)
.into();
@ -2567,4 +2565,33 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
pub fn activation(&self) -> GcCell<'gc, Activation<'gc>> {
self.activation
}
#[allow(dead_code)]
pub fn base_clip(&self) -> DisplayObject<'gc> {
self.activation.read().base_clip()
}
/// The current target clip for the executing code.
/// This is the movie clip that contains the bytecode.
/// Timeline actions like `GotoFrame` use this because
/// a goto after an invalid tellTarget has no effect.
pub fn target_clip(&self) -> Option<DisplayObject<'gc>> {
self.activation.read().target_clip()
}
/// The current target clip of the executing code.
/// Actions that affect `root` after an invalid `tellTarget` will use this.
///
/// The `root` is determined relative to the base clip that defined the
pub fn target_clip_or_root(&self) -> DisplayObject<'gc> {
self.activation
.read()
.target_clip()
.unwrap_or_else(|| self.base_clip().root())
}
/// Obtain the value of `_root`.
pub fn root_object(&self, _context: &mut UpdateContext<'_, 'gc, '_>) -> Value<'gc> {
self.base_clip().root().object()
}
}