avm1: Show stack frame with the avm_debug feature
This commit is contained in:
parent
c976cf8efb
commit
51321713b5
|
@ -39,7 +39,7 @@ pub mod xml_object;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::avm1::activation::Activation;
|
use crate::avm1::activation::{Activation, ActivationIdentifier};
|
||||||
use crate::avm1::error::Error;
|
use crate::avm1::error::Error;
|
||||||
use crate::avm1::listeners::SystemListener;
|
use crate::avm1::listeners::SystemListener;
|
||||||
pub use globals::SystemPrototypes;
|
pub use globals::SystemPrototypes;
|
||||||
|
@ -131,9 +131,10 @@ impl<'gc> Avm1<'gc> {
|
||||||
/// Add a stack frame that executes code in timeline scope
|
/// Add a stack frame that executes code in timeline scope
|
||||||
///
|
///
|
||||||
/// This creates a new frame stack.
|
/// This creates a new frame stack.
|
||||||
pub fn run_stack_frame_for_action(
|
pub fn run_stack_frame_for_action<S: Into<Cow<'static, str>>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
active_clip: DisplayObject<'gc>,
|
active_clip: DisplayObject<'gc>,
|
||||||
|
name: S,
|
||||||
swf_version: u8,
|
swf_version: u8,
|
||||||
code: SwfSlice,
|
code: SwfSlice,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
@ -145,6 +146,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
|
|
||||||
let mut parent_activation = Activation::from_nothing(
|
let mut parent_activation = Activation::from_nothing(
|
||||||
self,
|
self,
|
||||||
|
ActivationIdentifier::root("[Actions Parent]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
self.global_object_cell(),
|
self.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -165,6 +167,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
let constant_pool = parent_activation.avm.constant_pool;
|
let constant_pool = parent_activation.avm.constant_pool;
|
||||||
let mut child_activation = Activation::from_action(
|
let mut child_activation = Activation::from_action(
|
||||||
parent_activation.avm,
|
parent_activation.avm,
|
||||||
|
parent_activation.id.child(name),
|
||||||
swf_version,
|
swf_version,
|
||||||
child_scope,
|
child_scope,
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
@ -204,6 +207,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
);
|
);
|
||||||
let mut activation = Activation::from_action(
|
let mut activation = Activation::from_action(
|
||||||
self,
|
self,
|
||||||
|
ActivationIdentifier::root("[Display Object]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
child_scope,
|
child_scope,
|
||||||
self.constant_pool,
|
self.constant_pool,
|
||||||
|
@ -231,6 +235,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
|
|
||||||
let mut parent_activation = Activation::from_nothing(
|
let mut parent_activation = Activation::from_nothing(
|
||||||
self,
|
self,
|
||||||
|
ActivationIdentifier::root("[Init Parent]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
self.global_object_cell(),
|
self.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -252,6 +257,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
let constant_pool = parent_activation.avm.constant_pool;
|
let constant_pool = parent_activation.avm.constant_pool;
|
||||||
let mut child_activation = Activation::from_action(
|
let mut child_activation = Activation::from_action(
|
||||||
parent_activation.avm,
|
parent_activation.avm,
|
||||||
|
parent_activation.id.child("[Init]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
child_scope,
|
child_scope,
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
@ -284,6 +290,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
self,
|
self,
|
||||||
|
ActivationIdentifier::root(name.to_owned()),
|
||||||
swf_version,
|
swf_version,
|
||||||
self.global_object_cell(),
|
self.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -294,7 +301,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
search_prototype(Some(obj), name, &mut activation, context, obj).map(|r| (r.0, r.1));
|
search_prototype(Some(obj), name, &mut activation, context, obj).map(|r| (r.0, r.1));
|
||||||
|
|
||||||
if let Ok((callback, base_proto)) = search_result {
|
if let Ok((callback, base_proto)) = search_result {
|
||||||
let _ = callback.call(&mut activation, context, obj, base_proto, args);
|
let _ = callback.call(name, &mut activation, context, obj, base_proto, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +316,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
) {
|
) {
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
self,
|
self,
|
||||||
|
ActivationIdentifier::root("[System Listeners]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
self.global_object_cell(),
|
self.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -319,7 +327,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
let mut handlers = listeners.prepare_handlers(&mut activation, context, method);
|
let mut handlers = listeners.prepare_handlers(&mut activation, context, method);
|
||||||
|
|
||||||
for (listener, handler) in handlers.drain(..) {
|
for (listener, handler) in handlers.drain(..) {
|
||||||
let _ = handler.call(&mut activation, context, listener, None, &args);
|
let _ = handler.call(method, &mut activation, context, listener, None, &args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
use swf::avm1::read::Reader;
|
use swf::avm1::read::Reader;
|
||||||
use swf::avm1::types::{Action, CatchVar, Function, TryBlock};
|
use swf::avm1::types::{Action, CatchVar, Function, TryBlock};
|
||||||
use url::form_urlencoded;
|
use url::form_urlencoded;
|
||||||
|
@ -88,8 +89,58 @@ enum FrameControl<'gc> {
|
||||||
Return(ReturnType<'gc>),
|
Return(ReturnType<'gc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ActivationIdentifier<'a> {
|
||||||
|
parent: Option<&'a ActivationIdentifier<'a>>,
|
||||||
|
name: Cow<'static, str>,
|
||||||
|
depth: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ActivationIdentifier<'_> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if let Some(parent) = self.parent {
|
||||||
|
write!(f, "{} / ", parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.write_str(&self.name)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ActivationIdentifier<'a> {
|
||||||
|
pub fn root<S: Into<Cow<'static, str>>>(name: S) -> Self {
|
||||||
|
Self {
|
||||||
|
parent: None,
|
||||||
|
name: name.into(),
|
||||||
|
depth: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn child<S: Into<Cow<'static, str>>>(&'a self, name: S) -> Self {
|
||||||
|
Self {
|
||||||
|
parent: Some(self),
|
||||||
|
name: name.into(),
|
||||||
|
depth: self.depth + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn depth(&self) -> usize {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'gc> gc_arena::Collect for ActivationIdentifier<'gc> {
|
||||||
|
fn needs_trace() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn trace(&self, _cc: gc_arena::CollectionContext) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Collect)]
|
#[derive(Collect)]
|
||||||
#[collect(no_drop)]
|
#[collect(unsafe_drop)]
|
||||||
pub struct Activation<'a, 'gc: 'a> {
|
pub struct Activation<'a, 'gc: 'a> {
|
||||||
pub avm: &'a mut Avm1<'gc>,
|
pub avm: &'a mut Avm1<'gc>,
|
||||||
|
|
||||||
|
@ -137,11 +188,24 @@ pub struct Activation<'a, 'gc: 'a> {
|
||||||
/// The current target display object of this stack frame.
|
/// The current target display object of this stack frame.
|
||||||
/// This can be changed with `tellTarget` (via `ActionSetTarget` and `ActionSetTarget2`).
|
/// This can be changed with `tellTarget` (via `ActionSetTarget` and `ActionSetTarget2`).
|
||||||
target_clip: Option<DisplayObject<'gc>>,
|
target_clip: Option<DisplayObject<'gc>>,
|
||||||
|
|
||||||
|
/// An identifier to refer to this activation by, when debugging.
|
||||||
|
/// This is often the name of a function (if known), or some static name to indicate where
|
||||||
|
/// in the code it is (for example, a with{} block).
|
||||||
|
pub id: ActivationIdentifier<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Activation<'_, '_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
avm_debug!("END {}", self.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn from_action(
|
pub fn from_action(
|
||||||
avm: &'a mut Avm1<'gc>,
|
avm: &'a mut Avm1<'gc>,
|
||||||
|
id: ActivationIdentifier<'a>,
|
||||||
swf_version: u8,
|
swf_version: u8,
|
||||||
scope: GcCell<'gc, Scope<'gc>>,
|
scope: GcCell<'gc, Scope<'gc>>,
|
||||||
constant_pool: GcCell<'gc, Vec<String>>,
|
constant_pool: GcCell<'gc, Vec<String>>,
|
||||||
|
@ -149,8 +213,10 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
arguments: Option<Object<'gc>>,
|
arguments: Option<Object<'gc>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
avm_debug!("START {}", id);
|
||||||
Self {
|
Self {
|
||||||
avm,
|
avm,
|
||||||
|
id,
|
||||||
swf_version,
|
swf_version,
|
||||||
scope,
|
scope,
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
@ -164,9 +230,16 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new activation to run a block of code with a given scope.
|
/// Create a new activation to run a block of code with a given scope.
|
||||||
pub fn with_new_scope<'b>(&'b mut self, scope: GcCell<'gc, Scope<'gc>>) -> Activation<'b, 'gc> {
|
pub fn with_new_scope<'b, S: Into<Cow<'static, str>>>(
|
||||||
|
&'b mut self,
|
||||||
|
name: S,
|
||||||
|
scope: GcCell<'gc, Scope<'gc>>,
|
||||||
|
) -> Activation<'b, 'gc> {
|
||||||
|
let id = self.id.child(name);
|
||||||
|
avm_debug!("START {}", id);
|
||||||
Activation {
|
Activation {
|
||||||
avm: self.avm,
|
avm: self.avm,
|
||||||
|
id,
|
||||||
swf_version: self.swf_version,
|
swf_version: self.swf_version,
|
||||||
scope,
|
scope,
|
||||||
constant_pool: self.constant_pool,
|
constant_pool: self.constant_pool,
|
||||||
|
@ -185,6 +258,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
/// activation frame with access to the global context.
|
/// activation frame with access to the global context.
|
||||||
pub fn from_nothing(
|
pub fn from_nothing(
|
||||||
avm: &'a mut Avm1<'gc>,
|
avm: &'a mut Avm1<'gc>,
|
||||||
|
id: ActivationIdentifier<'a>,
|
||||||
swf_version: u8,
|
swf_version: u8,
|
||||||
globals: Object<'gc>,
|
globals: Object<'gc>,
|
||||||
mc: MutationContext<'gc, '_>,
|
mc: MutationContext<'gc, '_>,
|
||||||
|
@ -193,9 +267,11 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
let global_scope = GcCell::allocate(mc, Scope::from_global_object(globals));
|
let global_scope = GcCell::allocate(mc, Scope::from_global_object(globals));
|
||||||
let child_scope = GcCell::allocate(mc, Scope::new_local_scope(global_scope, mc));
|
let child_scope = GcCell::allocate(mc, Scope::new_local_scope(global_scope, mc));
|
||||||
let empty_constant_pool = GcCell::allocate(mc, Vec::new());
|
let empty_constant_pool = GcCell::allocate(mc, Vec::new());
|
||||||
|
avm_debug!("START {}", id);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
avm,
|
avm,
|
||||||
|
id,
|
||||||
swf_version,
|
swf_version,
|
||||||
scope: child_scope,
|
scope: child_scope,
|
||||||
constant_pool: empty_constant_pool,
|
constant_pool: empty_constant_pool,
|
||||||
|
@ -209,8 +285,9 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a stack frame that executes code in timeline scope
|
/// Add a stack frame that executes code in timeline scope
|
||||||
pub fn run_child_frame_for_action(
|
pub fn run_child_frame_for_action<S: Into<Cow<'static, str>>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
name: S,
|
||||||
active_clip: DisplayObject<'gc>,
|
active_clip: DisplayObject<'gc>,
|
||||||
swf_version: u8,
|
swf_version: u8,
|
||||||
code: SwfSlice,
|
code: SwfSlice,
|
||||||
|
@ -218,6 +295,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
) -> Result<ReturnType<'gc>, Error<'gc>> {
|
) -> Result<ReturnType<'gc>, Error<'gc>> {
|
||||||
let mut parent_activation = Activation::from_nothing(
|
let mut parent_activation = Activation::from_nothing(
|
||||||
self.avm,
|
self.avm,
|
||||||
|
self.id.child("[Actions Parent]"),
|
||||||
swf_version,
|
swf_version,
|
||||||
self.avm.globals,
|
self.avm.globals,
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -237,6 +315,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
let constant_pool = parent_activation.avm.constant_pool;
|
let constant_pool = parent_activation.avm.constant_pool;
|
||||||
let mut child_activation = Activation::from_action(
|
let mut child_activation = Activation::from_action(
|
||||||
parent_activation.avm,
|
parent_activation.avm,
|
||||||
|
parent_activation.id.child(name),
|
||||||
swf_version,
|
swf_version,
|
||||||
child_scope,
|
child_scope,
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
@ -248,8 +327,9 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a stack frame that executes code in initializer scope.
|
/// Add a stack frame that executes code in initializer scope.
|
||||||
pub fn run_with_child_frame_for_display_object<'c, F, R>(
|
pub fn run_with_child_frame_for_display_object<'c, F, R, S: Into<Cow<'static, str>>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
name: S,
|
||||||
active_clip: DisplayObject<'gc>,
|
active_clip: DisplayObject<'gc>,
|
||||||
swf_version: u8,
|
swf_version: u8,
|
||||||
action_context: &mut UpdateContext<'c, 'gc, '_>,
|
action_context: &mut UpdateContext<'c, 'gc, '_>,
|
||||||
|
@ -273,6 +353,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
let constant_pool = self.avm.constant_pool;
|
let constant_pool = self.avm.constant_pool;
|
||||||
let mut activation = Activation::from_action(
|
let mut activation = Activation::from_action(
|
||||||
self.avm,
|
self.avm,
|
||||||
|
self.id.child(name),
|
||||||
swf_version,
|
swf_version,
|
||||||
child_scope,
|
child_scope,
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
@ -311,7 +392,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
//Executing beyond the end of a function constitutes an implicit return.
|
//Executing beyond the end of a function constitutes an implicit return.
|
||||||
Ok(FrameControl::Return(ReturnType::Implicit))
|
Ok(FrameControl::Return(ReturnType::Implicit))
|
||||||
} else if let Some(action) = reader.read_action()? {
|
} else if let Some(action) = reader.read_action()? {
|
||||||
avm_debug!("Action: {:?}", action);
|
avm_debug!("({}) Action: {:?}", self.id.depth(), action);
|
||||||
|
|
||||||
let result = match action {
|
let result = match action {
|
||||||
Action::Add => self.action_add(context),
|
Action::Add => self.action_add(context),
|
||||||
|
@ -654,6 +735,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
if let Some(frame) = frame {
|
if let Some(frame) = frame {
|
||||||
for action in clip.actions_on_frame(context, frame) {
|
for action in clip.actions_on_frame(context, frame) {
|
||||||
let _ = self.run_child_frame_for_action(
|
let _ = self.run_child_frame_for_action(
|
||||||
|
"[Frame Call]",
|
||||||
self.target_clip_or_root(),
|
self.target_clip_or_root(),
|
||||||
self.current_swf_version(),
|
self.current_swf_version(),
|
||||||
action,
|
action,
|
||||||
|
@ -687,7 +769,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
.target_clip_or_root()
|
.target_clip_or_root()
|
||||||
.object()
|
.object()
|
||||||
.coerce_to_object(self, context);
|
.coerce_to_object(self, context);
|
||||||
let result = target_fn.call(self, context, this, None, &args)?;
|
let result = target_fn.call(&fn_name, self, context, this, None, &args)?;
|
||||||
self.avm.push(result);
|
self.avm.push(result);
|
||||||
|
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -712,12 +794,12 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
.target_clip_or_root()
|
.target_clip_or_root()
|
||||||
.object()
|
.object()
|
||||||
.coerce_to_object(self, context);
|
.coerce_to_object(self, context);
|
||||||
let result = object.call(self, context, this, None, &args)?;
|
let result = object.call("[Anonymous]", self, context, this, None, &args)?;
|
||||||
self.avm.push(result);
|
self.avm.push(result);
|
||||||
}
|
}
|
||||||
Value::String(name) => {
|
Value::String(name) => {
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
let result = object.call(self, context, object, None, &args)?;
|
let result = object.call("[Anonymous]", self, context, object, None, &args)?;
|
||||||
self.avm.push(result);
|
self.avm.push(result);
|
||||||
} else {
|
} else {
|
||||||
let result = object.call_method(&name, &args, self, context)?;
|
let result = object.call_method(&name, &args, self, context)?;
|
||||||
|
@ -1601,7 +1683,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: What happens if you `ActionNewMethod` without a method name?
|
//TODO: What happens if you `ActionNewMethod` without a method name?
|
||||||
constructor.call(self, context, this, None, &args)?;
|
constructor.call("[ctor]", self, context, this, None, &args)?;
|
||||||
|
|
||||||
self.avm.push(this);
|
self.avm.push(this);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1652,7 +1734,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.call(self, context, this, None, &args)?;
|
constructor.call("[ctor]", self, context, this, None, &args)?;
|
||||||
|
|
||||||
self.avm.push(this);
|
self.avm.push(this);
|
||||||
|
|
||||||
|
@ -2247,7 +2329,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let object = self.avm.pop().coerce_to_object(self, context);
|
let object = self.avm.pop().coerce_to_object(self, context);
|
||||||
let with_scope = Scope::new_with_scope(self.scope_cell(), object, context.gc_context);
|
let with_scope = Scope::new_with_scope(self.scope_cell(), object, context.gc_context);
|
||||||
let mut new_activation = self.with_new_scope(with_scope);
|
let mut new_activation = self.with_new_scope("[With]", with_scope);
|
||||||
if let ReturnType::Explicit(value) = new_activation.run_actions(context, code)? {
|
if let ReturnType::Explicit(value) = new_activation.run_actions(context, code)? {
|
||||||
Ok(FrameControl::Return(ReturnType::Explicit(value)))
|
Ok(FrameControl::Return(ReturnType::Explicit(value)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -2270,6 +2352,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
if let Err(Error::ThrownValue(value)) = &result {
|
if let Err(Error::ThrownValue(value)) = &result {
|
||||||
let mut activation = Activation::from_action(
|
let mut activation = Activation::from_action(
|
||||||
self.avm,
|
self.avm,
|
||||||
|
self.id.child("[Catch]"),
|
||||||
self.swf_version,
|
self.swf_version,
|
||||||
self.scope,
|
self.scope,
|
||||||
self.constant_pool,
|
self.constant_pool,
|
||||||
|
|
|
@ -222,6 +222,7 @@ impl<'gc> Executable<'gc> {
|
||||||
/// create a new stack frame and execute the action data yourself.
|
/// create a new stack frame and execute the action data yourself.
|
||||||
pub fn exec(
|
pub fn exec(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
ac: &mut UpdateContext<'_, 'gc, '_>,
|
ac: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -278,8 +279,29 @@ impl<'gc> Executable<'gc> {
|
||||||
.unwrap_or(ac.player_version)
|
.unwrap_or(ac.player_version)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let name = if cfg!(feature = "avm_debug") {
|
||||||
|
let mut result = match &af.name {
|
||||||
|
None => name.to_string(),
|
||||||
|
Some(name) => name.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
result.push('(');
|
||||||
|
for i in 0..args.len() {
|
||||||
|
result.push_str(args.get(i).unwrap().type_of());
|
||||||
|
if i < args.len() - 1 {
|
||||||
|
result.push_str(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(')');
|
||||||
|
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
af.name.clone().unwrap_or_else(|| name.to_string())
|
||||||
|
};
|
||||||
|
|
||||||
let mut frame = Activation::from_action(
|
let mut frame = Activation::from_action(
|
||||||
activation.avm,
|
activation.avm,
|
||||||
|
activation.id.child(name),
|
||||||
effective_ver,
|
effective_ver,
|
||||||
child_scope,
|
child_scope,
|
||||||
af.constant_pool,
|
af.constant_pool,
|
||||||
|
@ -468,9 +490,9 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.base.set(name, value, activation, context)
|
self.base.set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -478,7 +500,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(exec) = self.as_executable() {
|
if let Some(exec) = self.as_executable() {
|
||||||
exec.exec(activation, context, this, base_proto, args)
|
exec.exec(name, activation, context, this, base_proto, args)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
|
@ -811,7 +811,7 @@ fn sort_compare_custom<'gc>(
|
||||||
// TODO: Handle errors.
|
// TODO: Handle errors.
|
||||||
let args = [a.clone(), b.clone()];
|
let args = [a.clone(), b.clone()];
|
||||||
let ret = compare_fn
|
let ret = compare_fn
|
||||||
.call(activation, context, this, None, &args)
|
.call("[Compare]", activation, context, this, None, &args)
|
||||||
.unwrap_or(Value::Undefined);
|
.unwrap_or(Value::Undefined);
|
||||||
match ret {
|
match ret {
|
||||||
Value::Number(n) if n > 0.0 => Ordering::Greater,
|
Value::Number(n) if n > 0.0 => Ordering::Greater,
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub fn call<'gc>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match func.as_executable() {
|
match func.as_executable() {
|
||||||
Some(exec) => exec.exec(activation, action_context, this, None, args),
|
Some(exec) => exec.exec("[Anonymous]", activation, action_context, this, None, args),
|
||||||
_ => Ok(Value::Undefined),
|
_ => Ok(Value::Undefined),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,14 @@ pub fn apply<'gc>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match func.as_executable() {
|
match func.as_executable() {
|
||||||
Some(exec) => exec.exec(activation, action_context, this, None, &child_args),
|
Some(exec) => exec.exec(
|
||||||
|
"[Anonymous]",
|
||||||
|
activation,
|
||||||
|
action_context,
|
||||||
|
this,
|
||||||
|
None,
|
||||||
|
&child_args,
|
||||||
|
),
|
||||||
_ => Ok(Value::Undefined),
|
_ => Ok(Value::Undefined),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
/// it can be changed by `Function.apply`/`Function.call`.
|
/// it can be changed by `Function.apply`/`Function.call`.
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -120,7 +121,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
log::warn!("Object method {} is not callable", name);
|
log::warn!("Object method {} is not callable", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
method.call(activation, context, (*self).into(), base_proto, args)
|
method.call(name, activation, context, (*self).into(), base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a setter defined in this object.
|
/// Call a setter defined in this object.
|
||||||
|
|
|
@ -247,6 +247,7 @@ impl<'gc> ScriptObject<'gc> {
|
||||||
this_proto.call_setter(name, value.clone(), activation, context)
|
this_proto.call_setter(name, value.clone(), activation, context)
|
||||||
{
|
{
|
||||||
let _ = rval.exec(
|
let _ = rval.exec(
|
||||||
|
"[Setter]",
|
||||||
activation,
|
activation,
|
||||||
context,
|
context,
|
||||||
this,
|
this,
|
||||||
|
@ -280,7 +281,8 @@ impl<'gc> ScriptObject<'gc> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(rval) = rval {
|
if let Some(rval) = rval {
|
||||||
let _ = rval.exec(activation, context, this, base_proto, &[value])?;
|
let _ =
|
||||||
|
rval.exec("[Setter]", activation, context, this, base_proto, &[value])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,7 +326,14 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(get) = exec {
|
if let Some(get) = exec {
|
||||||
get.exec(activation, context, this, Some((*self).into()), &[])
|
get.exec(
|
||||||
|
"[Getter]",
|
||||||
|
activation,
|
||||||
|
context,
|
||||||
|
this,
|
||||||
|
Some((*self).into()),
|
||||||
|
&[],
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
@ -359,6 +368,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
/// overrides that may need to interact with the underlying object.
|
/// overrides that may need to interact with the underlying object.
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
_name: &str,
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_this: Object<'gc>,
|
_this: Object<'gc>,
|
||||||
|
@ -735,6 +745,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use crate::avm1::activation::ActivationIdentifier;
|
||||||
use crate::avm1::globals::system::SystemProperties;
|
use crate::avm1::globals::system::SystemProperties;
|
||||||
use crate::avm1::property::Attribute::*;
|
use crate::avm1::property::Attribute::*;
|
||||||
use crate::avm1::Avm1;
|
use crate::avm1::Avm1;
|
||||||
|
@ -811,6 +822,7 @@ mod tests {
|
||||||
let globals = avm.global_object_cell();
|
let globals = avm.global_object_cell();
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
&mut avm,
|
&mut avm,
|
||||||
|
ActivationIdentifier::root("[Test]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
globals,
|
globals,
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
|
|
@ -89,9 +89,9 @@ impl<'gc> TObject<'gc> for SharedObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.base().set(name, value, activation, context)
|
self.base().set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -99,7 +99,7 @@ impl<'gc> TObject<'gc> for SharedObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
self.base()
|
self.base()
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -150,9 +150,9 @@ impl<'gc> TObject<'gc> for SoundObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.base().set(name, value, activation, context)
|
self.base().set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -160,7 +160,7 @@ impl<'gc> TObject<'gc> for SoundObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
self.base()
|
self.base()
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -218,9 +218,9 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -230,7 +230,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
|
||||||
self.0
|
self.0
|
||||||
.read()
|
.read()
|
||||||
.base
|
.base
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -101,9 +101,9 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> {
|
||||||
//TODO: What happens if you set `super.__proto__`?
|
//TODO: What happens if you set `super.__proto__`?
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_this: Object<'gc>,
|
_this: Object<'gc>,
|
||||||
|
@ -112,6 +112,7 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> {
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(constr) = self.super_constr(activation, context)? {
|
if let Some(constr) = self.super_constr(activation, context)? {
|
||||||
constr.call(
|
constr.call(
|
||||||
|
name,
|
||||||
activation,
|
activation,
|
||||||
context,
|
context,
|
||||||
self.0.read().child,
|
self.0.read().child,
|
||||||
|
@ -140,7 +141,7 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> {
|
||||||
log::warn!("Super method {} is not callable", name);
|
log::warn!("Super method {} is not callable", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
method.call(activation, context, child, base_proto, args)
|
method.call(name, activation, context, child, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::avm1::activation::Activation;
|
use crate::avm1::activation::{Activation, ActivationIdentifier};
|
||||||
use crate::avm1::error::Error;
|
use crate::avm1::error::Error;
|
||||||
use crate::avm1::globals::system::SystemProperties;
|
use crate::avm1::globals::system::SystemProperties;
|
||||||
use crate::avm1::{Avm1, Object, UpdateContext};
|
use crate::avm1::{Avm1, Object, UpdateContext};
|
||||||
|
@ -99,6 +99,7 @@ where
|
||||||
let globals = avm.global_object_cell();
|
let globals = avm.global_object_cell();
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
&mut avm,
|
&mut avm,
|
||||||
|
ActivationIdentifier::root("[Test]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
globals,
|
globals,
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -128,7 +129,7 @@ macro_rules! test_method {
|
||||||
$(
|
$(
|
||||||
args.push($arg.into());
|
args.push($arg.into());
|
||||||
)*
|
)*
|
||||||
assert_eq!(function.call(activation, context, object, None, &args)?, $out.into(), "{:?} => {:?} in swf {}", args, $out, version);
|
assert_eq!(function.call($name, activation, context, object, None, &args)?, $out.into(), "{:?} => {:?} in swf {}", args, $out, version);
|
||||||
)*
|
)*
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -501,8 +501,7 @@ impl<'gc> Value<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_of(&self) -> Value<'gc> {
|
pub fn type_of(&self) -> &'static str {
|
||||||
Value::String(
|
|
||||||
match self {
|
match self {
|
||||||
Value::Undefined => "undefined",
|
Value::Undefined => "undefined",
|
||||||
Value::Null => "null",
|
Value::Null => "null",
|
||||||
|
@ -511,8 +510,6 @@ impl<'gc> Value<'gc> {
|
||||||
Value::String(_) => "string",
|
Value::String(_) => "string",
|
||||||
Value::Object(object) => object.type_of(),
|
Value::Object(object) => object.type_of(),
|
||||||
}
|
}
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coerce_to_object(
|
pub fn coerce_to_object(
|
||||||
|
@ -525,6 +522,7 @@ impl<'gc> Value<'gc> {
|
||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -532,7 +530,7 @@ impl<'gc> Value<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Value::Object(object) = self {
|
if let Value::Object(object) = self {
|
||||||
object.call(activation, context, this, base_proto, args)
|
object.call(name, activation, context, this, base_proto, args)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,9 +154,9 @@ impl<'gc> TObject<'gc> for ValueObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.0.read().base.set(name, value, activation, context)
|
self.0.read().base.set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -166,7 +166,7 @@ impl<'gc> TObject<'gc> for ValueObject<'gc> {
|
||||||
self.0
|
self.0
|
||||||
.read()
|
.read()
|
||||||
.base
|
.base
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -85,9 +85,9 @@ impl<'gc> TObject<'gc> for XMLAttributesObject<'gc> {
|
||||||
);
|
);
|
||||||
self.base().set(name, value, activation, context)
|
self.base().set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -95,7 +95,7 @@ impl<'gc> TObject<'gc> for XMLAttributesObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
self.base()
|
self.base()
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -85,9 +85,9 @@ impl<'gc> TObject<'gc> for XMLIDMapObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.base().set(name, value, activation, context)
|
self.base().set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -95,7 +95,7 @@ impl<'gc> TObject<'gc> for XMLIDMapObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
self.base()
|
self.base()
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -77,9 +77,9 @@ impl<'gc> TObject<'gc> for XMLObject<'gc> {
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
self.base().set(name, value, activation, context)
|
self.base().set(name, value, activation, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
|
name: &str,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
|
@ -87,7 +87,7 @@ impl<'gc> TObject<'gc> for XMLObject<'gc> {
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
self.base()
|
self.base()
|
||||||
.call(activation, context, this, base_proto, args)
|
.call(name, activation, context, this, base_proto, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_setter(
|
fn call_setter(
|
||||||
|
|
|
@ -716,6 +716,7 @@ impl<'gc> EditText<'gc> {
|
||||||
let parent = self.parent().unwrap();
|
let parent = self.parent().unwrap();
|
||||||
|
|
||||||
activation.run_with_child_frame_for_display_object(
|
activation.run_with_child_frame_for_display_object(
|
||||||
|
"[Text Field Binding]",
|
||||||
parent,
|
parent,
|
||||||
context.swf.header().version,
|
context.swf.header().version,
|
||||||
context,
|
context,
|
||||||
|
@ -806,6 +807,7 @@ impl<'gc> EditText<'gc> {
|
||||||
// Note that this can call virtual setters, even though the opposite direction won't work
|
// Note that this can call virtual setters, even though the opposite direction won't work
|
||||||
// (virtual property changes do not affect the text field)
|
// (virtual property changes do not affect the text field)
|
||||||
activation.run_with_child_frame_for_display_object(
|
activation.run_with_child_frame_for_display_object(
|
||||||
|
"[Propagate Text Binding]",
|
||||||
self.parent().unwrap(),
|
self.parent().unwrap(),
|
||||||
context.swf.header().version,
|
context.swf.header().version,
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use crate::avm1::{Avm1, Object, StageObject, TObject, Value};
|
use crate::avm1::{Avm1, Object, StageObject, TObject, Value};
|
||||||
use crate::backend::audio::AudioStreamHandle;
|
use crate::backend::audio::AudioStreamHandle;
|
||||||
|
|
||||||
use crate::avm1::activation::Activation;
|
use crate::avm1::activation::{Activation, ActivationIdentifier};
|
||||||
use crate::character::Character;
|
use crate::character::Character;
|
||||||
use crate::context::{ActionType, RenderContext, UpdateContext};
|
use crate::context::{ActionType, RenderContext, UpdateContext};
|
||||||
use crate::display_object::{
|
use crate::display_object::{
|
||||||
|
@ -977,6 +977,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Mouse Pick]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -1042,6 +1043,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
if instantiated_from_avm && self.0.read().avm1_constructor.is_some() {
|
if instantiated_from_avm && self.0.read().avm1_constructor.is_some() {
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Construct]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -1067,7 +1069,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.0.write(context.gc_context).object = Some(object);
|
self.0.write(context.gc_context).object = Some(object);
|
||||||
let _ = constructor.call(&mut activation, context, object, None, &[]);
|
let _ = constructor.call("[ctor]", &mut activation, context, object, None, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1081,6 +1083,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
if let Some(init_object) = init_object {
|
if let Some(init_object) = init_object {
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Init]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Management of async loaders
|
//! Management of async loaders
|
||||||
|
|
||||||
use crate::avm1::activation::Activation;
|
use crate::avm1::activation::{Activation, ActivationIdentifier};
|
||||||
use crate::avm1::{Object, TObject, Value};
|
use crate::avm1::{Object, TObject, Value};
|
||||||
use crate::backend::navigator::OwnedFuture;
|
use crate::backend::navigator::OwnedFuture;
|
||||||
use crate::context::{ActionQueue, ActionType};
|
use crate::context::{ActionQueue, ActionType};
|
||||||
|
@ -476,6 +476,7 @@ impl<'gc> Loader<'gc> {
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Form Loader]"),
|
||||||
uc.swf.version(),
|
uc.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
uc.gc_context,
|
uc.gc_context,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::avm1::activation::Activation;
|
use crate::avm1::activation::{Activation, ActivationIdentifier};
|
||||||
use crate::avm1::debug::VariableDumper;
|
use crate::avm1::debug::VariableDumper;
|
||||||
use crate::avm1::globals::system::SystemProperties;
|
use crate::avm1::globals::system::SystemProperties;
|
||||||
use crate::avm1::listeners::SystemListener;
|
use crate::avm1::listeners::SystemListener;
|
||||||
|
@ -274,6 +274,7 @@ impl Player {
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Version Setter]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -390,6 +391,7 @@ impl Player {
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Variable Dumper]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -740,6 +742,7 @@ impl Player {
|
||||||
ActionType::Normal { bytecode } => {
|
ActionType::Normal { bytecode } => {
|
||||||
avm.run_stack_frame_for_action(
|
avm.run_stack_frame_for_action(
|
||||||
actions.clip,
|
actions.clip,
|
||||||
|
"[Frame]",
|
||||||
context.swf.header().version,
|
context.swf.header().version,
|
||||||
bytecode,
|
bytecode,
|
||||||
context,
|
context,
|
||||||
|
@ -752,6 +755,7 @@ impl Player {
|
||||||
} => {
|
} => {
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Construct]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
@ -765,6 +769,7 @@ impl Player {
|
||||||
object.set_proto(context.gc_context, Some(prototype));
|
object.set_proto(context.gc_context, Some(prototype));
|
||||||
for event in events {
|
for event in events {
|
||||||
let _ = activation.run_child_frame_for_action(
|
let _ = activation.run_child_frame_for_action(
|
||||||
|
"[Actions]",
|
||||||
actions.clip,
|
actions.clip,
|
||||||
context.swf.header().version,
|
context.swf.header().version,
|
||||||
event,
|
event,
|
||||||
|
@ -772,7 +777,14 @@ impl Player {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = constructor.call(&mut activation, context, object, None, &[]);
|
let _ = constructor.call(
|
||||||
|
"[ctor]",
|
||||||
|
&mut activation,
|
||||||
|
context,
|
||||||
|
object,
|
||||||
|
None,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -784,6 +796,7 @@ impl Player {
|
||||||
for event in events {
|
for event in events {
|
||||||
avm.run_stack_frame_for_action(
|
avm.run_stack_frame_for_action(
|
||||||
actions.clip,
|
actions.clip,
|
||||||
|
"[Construct]",
|
||||||
context.swf.header().version,
|
context.swf.header().version,
|
||||||
event,
|
event,
|
||||||
context,
|
context,
|
||||||
|
@ -1005,6 +1018,7 @@ impl Player {
|
||||||
self.update(|avm, context| {
|
self.update(|avm, context| {
|
||||||
let mut activation = Activation::from_nothing(
|
let mut activation = Activation::from_nothing(
|
||||||
avm,
|
avm,
|
||||||
|
ActivationIdentifier::root("[Flush]"),
|
||||||
context.swf.version(),
|
context.swf.version(),
|
||||||
avm.global_object_cell(),
|
avm.global_object_cell(),
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
|
|
Loading…
Reference in New Issue