From d470c52aeaa8272db89b8867950c70c51827a468 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Sun, 28 Jun 2020 15:39:49 +0200 Subject: [PATCH] avm1: Move root_object, target_clip_or_root, target_clip and base_clip from avm1 to StackFrame --- core/src/avm1.rs | 30 ---------- core/src/avm1/globals/color.rs | 2 +- core/src/avm1/globals/display_object.rs | 2 +- core/src/avm1/globals/movie_clip.rs | 4 +- core/src/avm1/globals/xml.rs | 2 +- core/src/avm1/stack_frame.rs | 75 +++++++++++++++++-------- 6 files changed, 56 insertions(+), 59 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 54713e33e..05dbce3c5 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -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> { - 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) diff --git a/core/src/avm1/globals/color.rs b/core/src/avm1/globals/color.rs index 92f467d1e..813052007 100644 --- a/core/src/avm1/globals/color.rs +++ b/core/src/avm1/globals/color.rs @@ -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) diff --git a/core/src/avm1/globals/display_object.rs b/core/src/avm1/globals/display_object.rs index 33964f623..21400e4eb 100644 --- a/core/src/avm1/globals/display_object.rs +++ b/core/src/avm1/globals/display_object.rs @@ -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, diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index 1bd1fca29..c930d77a8 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -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, 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) diff --git a/core/src/avm1/globals/xml.rs b/core/src/avm1/globals/xml.rs index 62dc509e2..b58a54760 100644 --- a/core/src/avm1/globals/xml.rs +++ b/core/src/avm1/globals/xml.rs @@ -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, diff --git a/core/src/avm1/stack_frame.rs b/core/src/avm1/stack_frame.rs index db879ebc1..f103f2a60 100644 --- a/core/src/avm1/stack_frame.rs +++ b/core/src/avm1/stack_frame.rs @@ -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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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> { + 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() + } }