Move AVM2 into the UpdateContext.
This commit is contained in:
parent
bfa5f8ae35
commit
8ebf5405e2
|
@ -843,6 +843,7 @@ mod tests {
|
|||
use crate::avm1::globals::system::SystemProperties;
|
||||
use crate::avm1::property::Attribute::*;
|
||||
use crate::avm1::{Avm1, Timers};
|
||||
use crate::avm2::Avm2;
|
||||
use crate::backend::audio::NullAudioBackend;
|
||||
use crate::backend::input::NullInputBackend;
|
||||
use crate::backend::navigator::NullNavigatorBackend;
|
||||
|
@ -864,7 +865,8 @@ mod tests {
|
|||
F: for<'a, 'gc> FnOnce(&mut Activation<'_, 'gc, '_>, Object<'gc>) -> R,
|
||||
{
|
||||
rootless_arena(|gc_context| {
|
||||
let mut avm = Avm1::new(gc_context, swf_version);
|
||||
let mut avm1 = Avm1::new(gc_context, swf_version);
|
||||
let mut avm2 = Avm2::new(gc_context);
|
||||
let swf = Arc::new(SwfMovie::empty(swf_version));
|
||||
let mut root: DisplayObject<'_> =
|
||||
MovieClip::new(SwfSlice::empty(swf.clone()), gc_context).into();
|
||||
|
@ -872,8 +874,8 @@ mod tests {
|
|||
let mut levels = BTreeMap::new();
|
||||
levels.insert(0, root);
|
||||
|
||||
let object = ScriptObject::object(gc_context, Some(avm.prototypes().object)).into();
|
||||
let globals = avm.global_object_cell();
|
||||
let object = ScriptObject::object(gc_context, Some(avm1.prototypes().object)).into();
|
||||
let globals = avm1.global_object_cell();
|
||||
|
||||
let mut context = UpdateContext {
|
||||
gc_context,
|
||||
|
@ -893,7 +895,7 @@ mod tests {
|
|||
library: &mut Library::default(),
|
||||
navigator: &mut NullNavigatorBackend::new(),
|
||||
renderer: &mut NullRenderer::new(),
|
||||
system_prototypes: avm.prototypes().clone(),
|
||||
system_prototypes: avm1.prototypes().clone(),
|
||||
mouse_hovered_object: None,
|
||||
mouse_position: &(Twips::new(0), Twips::new(0)),
|
||||
drag_object: &mut None,
|
||||
|
@ -907,7 +909,8 @@ mod tests {
|
|||
unbound_text_fields: &mut Vec::new(),
|
||||
timers: &mut Timers::new(),
|
||||
needs_render: &mut false,
|
||||
avm1: &mut avm,
|
||||
avm1: &mut avm1,
|
||||
avm2: &mut avm2,
|
||||
};
|
||||
|
||||
root.post_instantiation(&mut context, root, None, false);
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::avm1::activation::{Activation, ActivationIdentifier};
|
|||
use crate::avm1::error::Error;
|
||||
use crate::avm1::globals::system::SystemProperties;
|
||||
use crate::avm1::{Avm1, Object, Timers, UpdateContext};
|
||||
use crate::avm2::Avm2;
|
||||
use crate::backend::audio::NullAudioBackend;
|
||||
use crate::backend::input::NullInputBackend;
|
||||
use crate::backend::navigator::NullNavigatorBackend;
|
||||
|
@ -27,6 +28,7 @@ where
|
|||
F: FnOnce(&mut Activation<'_, 'gc, '_>, Object<'gc>) -> Result<(), Error<'gc>>,
|
||||
{
|
||||
let mut avm1 = Avm1::new(gc_context, swf_version);
|
||||
let mut avm2 = Avm2::new(gc_context);
|
||||
let swf = Arc::new(SwfMovie::empty(swf_version));
|
||||
let mut root: DisplayObject<'gc> =
|
||||
MovieClip::new(SwfSlice::empty(swf.clone()), gc_context).into();
|
||||
|
@ -69,6 +71,7 @@ where
|
|||
timers: &mut Timers::new(),
|
||||
needs_render: &mut false,
|
||||
avm1: &mut avm1,
|
||||
avm2: &mut avm2,
|
||||
};
|
||||
root.post_instantiation(&mut context, root, None, false);
|
||||
root.set_name(context.gc_context, "");
|
||||
|
|
|
@ -85,20 +85,19 @@ impl<'gc> Avm2<'gc> {
|
|||
|
||||
/// Run a script's initializer method.
|
||||
pub fn run_script_initializer(
|
||||
&mut self,
|
||||
script: GcCell<'gc, Script<'gc>>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let mut init_activation = Activation::from_script(self, context, script, self.globals)?;
|
||||
let globals = context.avm2.globals;
|
||||
let mut init_activation = Activation::from_script(context.reborrow(), script, globals)?;
|
||||
|
||||
init_activation.run_stack_frame_for_script(context, script)
|
||||
init_activation.run_stack_frame_for_script(script)
|
||||
}
|
||||
|
||||
/// Load an ABC file embedded in a `SwfSlice`.
|
||||
///
|
||||
/// The `SwfSlice` must resolve to the contents of an ABC file.
|
||||
pub fn load_abc(
|
||||
&mut self,
|
||||
abc: SwfSlice,
|
||||
_abc_name: &str,
|
||||
_lazy_init: bool,
|
||||
|
@ -111,16 +110,15 @@ impl<'gc> Avm2<'gc> {
|
|||
|
||||
for i in (0..abc_file.scripts.len()).rev() {
|
||||
let script = tunit.load_script(i as u32, context.gc_context)?;
|
||||
let mut globals = self.globals();
|
||||
let mut globals = context.avm2.globals();
|
||||
let scope = Scope::push_scope(None, globals, context.gc_context);
|
||||
let mut null_activation = Activation::from_nothing(self, context);
|
||||
let mut null_activation = Activation::from_nothing(context.reborrow());
|
||||
|
||||
// TODO: Lazyinit means we shouldn't do this until traits are
|
||||
// actually mentioned...
|
||||
for trait_entry in script.read().traits()?.iter() {
|
||||
globals.install_foreign_trait(
|
||||
&mut null_activation,
|
||||
context,
|
||||
trait_entry.clone(),
|
||||
Some(scope),
|
||||
globals,
|
||||
|
@ -129,7 +127,7 @@ impl<'gc> Avm2<'gc> {
|
|||
|
||||
drop(null_activation);
|
||||
|
||||
self.run_script_initializer(script, context)?;
|
||||
Self::run_script_initializer(script, context)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,6 @@ use crate::avm2::script_object::{ScriptObject, ScriptObjectClass, ScriptObjectDa
|
|||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, CollectionContext, Gc, GcCell, MutationContext};
|
||||
use std::fmt;
|
||||
|
||||
|
@ -87,22 +86,17 @@ impl<'gc> Executable<'gc> {
|
|||
&self,
|
||||
unbound_reciever: Option<Object<'gc>>,
|
||||
arguments: &[Value<'gc>],
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
match self {
|
||||
Executable::Native(nf, reciever) => nf(
|
||||
activation,
|
||||
context,
|
||||
reciever.or(unbound_reciever),
|
||||
arguments,
|
||||
),
|
||||
Executable::Native(nf, reciever) => {
|
||||
nf(activation, reciever.or(unbound_reciever), arguments)
|
||||
}
|
||||
Executable::Action(bm) => {
|
||||
let reciever = bm.reciever.or(unbound_reciever);
|
||||
let mut activation = Activation::from_method(
|
||||
activation.avm2(),
|
||||
context,
|
||||
activation.context.reborrow(),
|
||||
bm.method,
|
||||
bm.scope,
|
||||
reciever,
|
||||
|
@ -110,7 +104,7 @@ impl<'gc> Executable<'gc> {
|
|||
base_proto,
|
||||
)?;
|
||||
|
||||
activation.run_actions(bm.method, context)
|
||||
activation.run_actions(bm.method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,8 +155,7 @@ impl<'gc> FunctionObject<'gc> {
|
|||
/// to be limited to interfaces (at least by the AS3 compiler in Animate
|
||||
/// CC 2020.)
|
||||
pub fn from_class(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
class: GcCell<'gc, Class<'gc>>,
|
||||
base_class: Option<Object<'gc>>,
|
||||
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
|
@ -174,7 +167,6 @@ impl<'gc> FunctionObject<'gc> {
|
|||
base_class,
|
||||
&QName::new(Namespace::public_namespace(), "prototype"),
|
||||
activation,
|
||||
context,
|
||||
)?
|
||||
.as_object()
|
||||
.map_err(|_| {
|
||||
|
@ -189,9 +181,9 @@ impl<'gc> FunctionObject<'gc> {
|
|||
.into()
|
||||
});
|
||||
|
||||
super_proto?.derive(activation, context, class, scope)?
|
||||
super_proto?.derive(activation, class, scope)?
|
||||
} else {
|
||||
ScriptObject::bare_object(context.gc_context)
|
||||
ScriptObject::bare_object(activation.context.gc_context)
|
||||
};
|
||||
|
||||
let mut interfaces = Vec::new();
|
||||
|
@ -199,8 +191,8 @@ impl<'gc> FunctionObject<'gc> {
|
|||
for interface_name in interface_names {
|
||||
let interface = if let Some(scope) = scope {
|
||||
scope
|
||||
.write(context.gc_context)
|
||||
.resolve(&interface_name, activation, context)?
|
||||
.write(activation.context.gc_context)
|
||||
.resolve(&interface_name, activation)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -215,7 +207,6 @@ impl<'gc> FunctionObject<'gc> {
|
|||
interface,
|
||||
&QName::new(Namespace::public_namespace(), "prototype"),
|
||||
activation,
|
||||
context,
|
||||
)?
|
||||
.as_object()?;
|
||||
|
||||
|
@ -223,7 +214,7 @@ impl<'gc> FunctionObject<'gc> {
|
|||
}
|
||||
|
||||
if !interfaces.is_empty() {
|
||||
class_proto.set_interfaces(context.gc_context, interfaces);
|
||||
class_proto.set_interfaces(activation.context.gc_context, interfaces);
|
||||
}
|
||||
|
||||
let fn_proto = activation.avm2().prototypes().function;
|
||||
|
@ -232,7 +223,7 @@ impl<'gc> FunctionObject<'gc> {
|
|||
let initializer = class_read.instance_init();
|
||||
|
||||
let mut constr: Object<'gc> = FunctionObject(GcCell::allocate(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
FunctionObjectData {
|
||||
base: ScriptObjectData::base_new(
|
||||
Some(fn_proto),
|
||||
|
@ -242,26 +233,26 @@ impl<'gc> FunctionObject<'gc> {
|
|||
initializer,
|
||||
scope,
|
||||
None,
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
)),
|
||||
},
|
||||
))
|
||||
.into();
|
||||
|
||||
constr.install_dynamic_property(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
QName::new(Namespace::public_namespace(), "prototype"),
|
||||
class_proto.into(),
|
||||
)?;
|
||||
class_proto.install_dynamic_property(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
QName::new(Namespace::public_namespace(), "constructor"),
|
||||
constr.into(),
|
||||
)?;
|
||||
|
||||
let class_initializer = class_read.class_init();
|
||||
let class_constr = FunctionObject::from_method(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
class_initializer,
|
||||
scope,
|
||||
class_constr_proto,
|
||||
|
@ -346,15 +337,14 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
self,
|
||||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let read = self.0.read();
|
||||
let rv = read.base.get_property_local(reciever, name, activation)?;
|
||||
|
||||
drop(read);
|
||||
|
||||
rv.resolve(activation, context)
|
||||
rv.resolve(activation)
|
||||
}
|
||||
|
||||
fn set_property_local(
|
||||
|
@ -362,17 +352,16 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let mut write = self.0.write(context.gc_context);
|
||||
let mut write = self.0.write(activation.context.gc_context);
|
||||
let rv = write
|
||||
.base
|
||||
.set_property_local(reciever, name, value, activation, context)?;
|
||||
.set_property_local(reciever, name, value, activation)?;
|
||||
|
||||
drop(write);
|
||||
|
||||
rv.resolve(activation, context)?;
|
||||
rv.resolve(activation)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -382,17 +371,16 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let mut write = self.0.write(context.gc_context);
|
||||
let mut write = self.0.write(activation.context.gc_context);
|
||||
let rv = write
|
||||
.base
|
||||
.init_property_local(reciever, name, value, activation, context)?;
|
||||
.init_property_local(reciever, name, value, activation)?;
|
||||
|
||||
drop(write);
|
||||
|
||||
rv.resolve(activation, context)?;
|
||||
rv.resolve(activation)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -526,12 +514,11 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
self,
|
||||
reciever: Option<Object<'gc>>,
|
||||
arguments: &[Value<'gc>],
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(exec) = &self.0.read().exec {
|
||||
exec.exec(reciever, arguments, activation, context, base_proto)
|
||||
exec.exec(reciever, arguments, activation, base_proto)
|
||||
} else {
|
||||
Err("Not a callable function!".into())
|
||||
}
|
||||
|
@ -539,15 +526,14 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
|
||||
fn construct(
|
||||
&self,
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::FunctionObject(*self);
|
||||
let base = ScriptObjectData::base_new(Some(this), ScriptObjectClass::NoClass);
|
||||
|
||||
Ok(FunctionObject(GcCell::allocate(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
FunctionObjectData { base, exec: None },
|
||||
))
|
||||
.into())
|
||||
|
@ -555,8 +541,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
|
||||
fn derive(
|
||||
&self,
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
class: GcCell<'gc, Class<'gc>>,
|
||||
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
|
@ -567,7 +552,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
);
|
||||
|
||||
Ok(FunctionObject(GcCell::allocate(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
FunctionObjectData { base, exec: None },
|
||||
))
|
||||
.into())
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::avm2::script_object::ScriptObject;
|
|||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, MutationContext};
|
||||
use std::f64::NAN;
|
||||
|
||||
|
@ -19,8 +18,7 @@ mod function;
|
|||
mod object;
|
||||
|
||||
fn trace<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `Class`
|
||||
|
@ -13,8 +12,7 @@ use gc_arena::MutationContext;
|
|||
/// Notably, you cannot construct new classes this way, so this returns an
|
||||
/// error.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.display.DisplayObject`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.display.DisplayObjectContainer`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.display.InteractiveObject`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.display.MovieClip`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.display.Sprite`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -5,13 +5,11 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `flash.events.EventDispatcher`'s constructor.
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
|
|
@ -7,13 +7,11 @@ use crate::avm2::object::{Object, TObject};
|
|||
use crate::avm2::script_object::ScriptObject;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `Function`
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -22,8 +20,7 @@ pub fn constructor<'gc>(
|
|||
|
||||
/// Implements `Function.prototype.call`
|
||||
fn call<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
func: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -32,9 +29,9 @@ fn call<'gc>(
|
|||
|
||||
if let Some(func) = func {
|
||||
if args.len() > 1 {
|
||||
Ok(func.call(this, &args[1..], activation, context, base_proto)?)
|
||||
Ok(func.call(this, &args[1..], activation, base_proto)?)
|
||||
} else {
|
||||
Ok(func.call(this, &[], activation, context, base_proto)?)
|
||||
Ok(func.call(this, &[], activation, base_proto)?)
|
||||
}
|
||||
} else {
|
||||
Err("Not a callable function".into())
|
||||
|
|
|
@ -6,13 +6,11 @@ use crate::avm2::names::{Namespace, QName};
|
|||
use crate::avm2::object::{Object, TObject};
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `Object`
|
||||
pub fn constructor<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Option<Object<'gc>>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -21,44 +19,40 @@ pub fn constructor<'gc>(
|
|||
|
||||
/// Implements `Object.prototype.toString`
|
||||
fn to_string<'gc>(
|
||||
_: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
_: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
Ok(this
|
||||
.map(|t| t.to_string(context.gc_context))
|
||||
.map(|t| t.to_string(activation.context.gc_context))
|
||||
.unwrap_or(Ok(Value::Undefined))?)
|
||||
}
|
||||
|
||||
/// Implements `Object.prototype.toLocaleString`
|
||||
fn to_locale_string<'gc>(
|
||||
_: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
_: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
Ok(this
|
||||
.map(|t| t.to_string(context.gc_context))
|
||||
.map(|t| t.to_string(activation.context.gc_context))
|
||||
.unwrap_or(Ok(Value::Undefined))?)
|
||||
}
|
||||
|
||||
/// Implements `Object.prototype.valueOf`
|
||||
fn value_of<'gc>(
|
||||
_: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
_: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
Ok(this
|
||||
.map(|t| t.value_of(context.gc_context))
|
||||
.map(|t| t.value_of(activation.context.gc_context))
|
||||
.unwrap_or(Ok(Value::Undefined))?)
|
||||
}
|
||||
|
||||
/// `Object.prototype.hasOwnProperty`
|
||||
pub fn has_own_property<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -79,8 +73,7 @@ pub fn has_own_property<'gc>(
|
|||
|
||||
/// `Object.prototype.isPrototypeOf`
|
||||
pub fn is_prototype_of<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -102,8 +95,7 @@ pub fn is_prototype_of<'gc>(
|
|||
|
||||
/// `Object.prototype.propertyIsEnumerable`
|
||||
pub fn property_is_enumerable<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -124,8 +116,7 @@ pub fn property_is_enumerable<'gc>(
|
|||
|
||||
/// `Object.prototype.setPropertyIsEnumerable`
|
||||
pub fn set_property_is_enumerable<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
|
@ -142,7 +133,7 @@ pub fn set_property_is_enumerable<'gc>(
|
|||
if let Some(ns) = this.resolve_any(name)? {
|
||||
if !ns.is_private() {
|
||||
let qname = QName::new(ns, name);
|
||||
this.set_local_property_is_enumerable(context.gc_context, &qname, is_enum)?;
|
||||
this.set_local_property_is_enumerable(activation.context.gc_context, &qname, is_enum)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::avm2::object::Object;
|
|||
use crate::avm2::script::TranslationUnit;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, CollectionContext, Gc, MutationContext};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
@ -30,8 +29,7 @@ pub struct CollectWrapper<T>(T);
|
|||
/// your function yields `None`, you must ensure that the top-most activation
|
||||
/// in the AVM1 runtime will return with the value of this function.
|
||||
pub type NativeMethod<'gc> = fn(
|
||||
&mut Activation<'_, 'gc>,
|
||||
&mut UpdateContext<'_, 'gc, '_>,
|
||||
&mut Activation<'_, 'gc, '_>,
|
||||
Option<Object<'gc>>,
|
||||
&[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error>;
|
||||
|
|
|
@ -10,7 +10,6 @@ use crate::avm2::script_object::ScriptObject;
|
|||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use ruffle_macros::enum_trait_object;
|
||||
use std::fmt::Debug;
|
||||
|
@ -32,8 +31,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
self,
|
||||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error>;
|
||||
|
||||
/// Retrieve a property by it's QName.
|
||||
|
@ -41,23 +39,22 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
&mut self,
|
||||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
if !self.has_instantiated_property(name) {
|
||||
for abc_trait in self.get_trait(name)? {
|
||||
self.install_trait(activation, context, abc_trait, reciever)?;
|
||||
self.install_trait(activation, abc_trait, reciever)?;
|
||||
}
|
||||
}
|
||||
|
||||
let has_no_getter = self.has_own_virtual_setter(name) && !self.has_own_virtual_getter(name);
|
||||
|
||||
if self.has_own_property(name)? && !has_no_getter {
|
||||
return self.get_property_local(reciever, name, activation, context);
|
||||
return self.get_property_local(reciever, name, activation);
|
||||
}
|
||||
|
||||
if let Some(mut proto) = self.proto() {
|
||||
return proto.get_property(reciever, name, activation, context);
|
||||
return proto.get_property(reciever, name, activation);
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
|
@ -85,8 +82,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Set a property by it's QName.
|
||||
|
@ -95,17 +91,16 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
if !self.has_instantiated_property(name) {
|
||||
for abc_trait in self.get_trait(name)? {
|
||||
self.install_trait(activation, context, abc_trait, reciever)?;
|
||||
self.install_trait(activation, abc_trait, reciever)?;
|
||||
}
|
||||
}
|
||||
|
||||
if self.has_own_virtual_setter(name) {
|
||||
return self.set_property_local(reciever, name, value, activation, context);
|
||||
return self.set_property_local(reciever, name, value, activation);
|
||||
}
|
||||
|
||||
let mut proto = self.proto();
|
||||
|
@ -114,13 +109,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
//we're calling a virtual setter. If you call `set_property` on
|
||||
//a non-virtual you will actually alter the prototype.
|
||||
if my_proto.has_own_virtual_setter(name) {
|
||||
return my_proto.set_property(reciever, name, value, activation, context);
|
||||
return my_proto.set_property(reciever, name, value, activation);
|
||||
}
|
||||
|
||||
proto = my_proto.proto();
|
||||
}
|
||||
|
||||
reciever.set_property_local(reciever, name, value, activation, context)
|
||||
reciever.set_property_local(reciever, name, value, activation)
|
||||
}
|
||||
|
||||
/// Init a property on this specific object.
|
||||
|
@ -129,8 +124,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Init a property by it's QName.
|
||||
|
@ -139,17 +133,16 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
if !self.has_instantiated_property(name) {
|
||||
for abc_trait in self.get_trait(name)? {
|
||||
self.install_trait(activation, context, abc_trait, reciever)?;
|
||||
self.install_trait(activation, abc_trait, reciever)?;
|
||||
}
|
||||
}
|
||||
|
||||
if self.has_own_virtual_setter(name) {
|
||||
return self.init_property_local(reciever, name, value, activation, context);
|
||||
return self.init_property_local(reciever, name, value, activation);
|
||||
}
|
||||
|
||||
let mut proto = self.proto();
|
||||
|
@ -158,13 +151,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
//we're calling a virtual setter. If you call `set_property` on
|
||||
//a non-virtual you will actually alter the prototype.
|
||||
if my_proto.has_own_virtual_setter(name) {
|
||||
return my_proto.init_property(reciever, name, value, activation, context);
|
||||
return my_proto.init_property(reciever, name, value, activation);
|
||||
}
|
||||
|
||||
proto = my_proto.proto();
|
||||
}
|
||||
|
||||
reciever.init_property_local(reciever, name, value, activation, context)
|
||||
reciever.init_property_local(reciever, name, value, activation)
|
||||
}
|
||||
|
||||
/// Retrieve a slot by it's index.
|
||||
|
@ -411,19 +404,17 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// object.
|
||||
fn install_trait(
|
||||
&mut self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
trait_entry: Trait<'gc>,
|
||||
reciever: Object<'gc>,
|
||||
) -> Result<(), Error> {
|
||||
self.install_foreign_trait(activation, context, trait_entry, self.get_scope(), reciever)
|
||||
self.install_foreign_trait(activation, trait_entry, self.get_scope(), reciever)
|
||||
}
|
||||
|
||||
/// Install a trait from anywyere.
|
||||
fn install_foreign_trait(
|
||||
&mut self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
trait_entry: Trait<'gc>,
|
||||
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
reciever: Object<'gc>,
|
||||
|
@ -444,7 +435,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
..
|
||||
} => {
|
||||
self.install_slot(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*slot_id,
|
||||
default_value.clone().unwrap_or(Value::Undefined),
|
||||
|
@ -454,37 +445,52 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
disp_id, method, ..
|
||||
} => {
|
||||
let function = FunctionObject::from_method(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
method.clone(),
|
||||
scope,
|
||||
fn_proto,
|
||||
Some(reciever),
|
||||
);
|
||||
self.install_method(context.gc_context, trait_name, *disp_id, function);
|
||||
self.install_method(
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*disp_id,
|
||||
function,
|
||||
);
|
||||
}
|
||||
TraitKind::Getter {
|
||||
disp_id, method, ..
|
||||
} => {
|
||||
let function = FunctionObject::from_method(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
method.clone(),
|
||||
scope,
|
||||
fn_proto,
|
||||
Some(reciever),
|
||||
);
|
||||
self.install_getter(context.gc_context, trait_name, *disp_id, function)?;
|
||||
self.install_getter(
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*disp_id,
|
||||
function,
|
||||
)?;
|
||||
}
|
||||
TraitKind::Setter {
|
||||
disp_id, method, ..
|
||||
} => {
|
||||
let function = FunctionObject::from_method(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
method.clone(),
|
||||
scope,
|
||||
fn_proto,
|
||||
Some(reciever),
|
||||
);
|
||||
self.install_setter(context.gc_context, trait_name, *disp_id, function)?;
|
||||
self.install_setter(
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*disp_id,
|
||||
function,
|
||||
)?;
|
||||
}
|
||||
TraitKind::Class { slot_id, class } => {
|
||||
let class_read = class.read();
|
||||
|
@ -494,7 +500,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
.unwrap_or_else(|| QName::dynamic_name("Object"));
|
||||
|
||||
let super_class: Result<Object<'gc>, Error> = self
|
||||
.get_property(reciever, &super_name, activation, context)?
|
||||
.get_property(reciever, &super_name, activation)?
|
||||
.as_object()
|
||||
.map_err(|_e| {
|
||||
format!("Could not resolve superclass {:?}", super_name.local_name())
|
||||
|
@ -507,9 +513,9 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
};
|
||||
|
||||
let (class_object, _cinit) =
|
||||
FunctionObject::from_class(activation, context, *class, super_class, scope)?;
|
||||
FunctionObject::from_class(activation, *class, super_class, scope)?;
|
||||
self.install_const(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
class_read.name().clone(),
|
||||
*slot_id,
|
||||
class_object.into(),
|
||||
|
@ -519,22 +525,29 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
slot_id, function, ..
|
||||
} => {
|
||||
let mut fobject = FunctionObject::from_method(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
function.clone(),
|
||||
scope,
|
||||
fn_proto,
|
||||
None,
|
||||
);
|
||||
let es3_proto =
|
||||
ScriptObject::object(context.gc_context, activation.avm2().prototypes().object);
|
||||
let es3_proto = ScriptObject::object(
|
||||
activation.context.gc_context,
|
||||
activation.avm2().prototypes().object,
|
||||
);
|
||||
|
||||
fobject.install_slot(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
QName::new(Namespace::public_namespace(), "prototype"),
|
||||
0,
|
||||
es3_proto.into(),
|
||||
);
|
||||
self.install_const(context.gc_context, trait_name, *slot_id, fobject.into());
|
||||
self.install_const(
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*slot_id,
|
||||
fobject.into(),
|
||||
);
|
||||
}
|
||||
TraitKind::Const {
|
||||
slot_id,
|
||||
|
@ -542,7 +555,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
..
|
||||
} => {
|
||||
self.install_const(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
trait_name,
|
||||
*slot_id,
|
||||
default_value.clone().unwrap_or(Value::Undefined),
|
||||
|
@ -558,8 +571,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
self,
|
||||
_reciever: Option<Object<'gc>>,
|
||||
_arguments: &[Value<'gc>],
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_base_proto: Option<Object<'gc>>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
Err("Object is not callable".into())
|
||||
|
@ -584,8 +596,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// purely so that host objects can be constructed by the VM.
|
||||
fn construct(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Object<'gc>, Error>;
|
||||
|
||||
|
@ -600,8 +611,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// traits.
|
||||
fn derive(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
class: GcCell<'gc, Class<'gc>>,
|
||||
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
) -> Result<Object<'gc>, Error>;
|
||||
|
@ -638,18 +648,12 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
#[allow(unused_mut)] //it's not unused
|
||||
fn is_instance_of(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
mut constructor: Object<'gc>,
|
||||
check_interfaces: bool,
|
||||
) -> Result<bool, Error> {
|
||||
let type_proto = constructor
|
||||
.get_property(
|
||||
constructor,
|
||||
&QName::dynamic_name("prototype"),
|
||||
activation,
|
||||
context,
|
||||
)?
|
||||
.get_property(constructor, &QName::dynamic_name("prototype"), activation)?
|
||||
.as_object()?;
|
||||
let mut my_proto = self.proto();
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::avm2::activation::Activation;
|
|||
use crate::avm2::function::Executable;
|
||||
use crate::avm2::object::Object;
|
||||
use crate::avm2::{Error, Value};
|
||||
use crate::context::UpdateContext;
|
||||
use std::fmt;
|
||||
|
||||
/// Represents the return value of a function call that has not yet executed.
|
||||
|
@ -83,11 +82,7 @@ impl<'gc> ReturnValue<'gc> {
|
|||
///
|
||||
/// All return values must eventually resolved - it is a compile error to
|
||||
/// fail to do so.
|
||||
pub fn resolve(
|
||||
self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
pub fn resolve(self, activation: &mut Activation<'_, 'gc, '_>) -> Result<Value<'gc>, Error> {
|
||||
match self {
|
||||
Self::Immediate(v) => Ok(v),
|
||||
Self::ResultOf {
|
||||
|
@ -95,13 +90,7 @@ impl<'gc> ReturnValue<'gc> {
|
|||
unbound_reciever,
|
||||
arguments,
|
||||
base_proto,
|
||||
} => executable.exec(
|
||||
unbound_reciever,
|
||||
&arguments,
|
||||
activation,
|
||||
context,
|
||||
base_proto,
|
||||
),
|
||||
} => executable.exec(unbound_reciever, &arguments, activation, base_proto),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::avm2::names::Multiname;
|
|||
use crate::avm2::object::{Object, TObject};
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::cell::Ref;
|
||||
|
||||
|
@ -100,8 +99,7 @@ impl<'gc> Scope<'gc> {
|
|||
pub fn find(
|
||||
&self,
|
||||
name: &Multiname<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Option<Object<'gc>>, Error> {
|
||||
if let Some(qname) = self.locals().resolve_multiname(name)? {
|
||||
if self.locals().has_property(&qname)? {
|
||||
|
@ -110,7 +108,7 @@ impl<'gc> Scope<'gc> {
|
|||
}
|
||||
|
||||
if let Some(scope) = self.parent() {
|
||||
return scope.find(name, activation, context);
|
||||
return scope.find(name, activation);
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
|
@ -123,8 +121,7 @@ impl<'gc> Scope<'gc> {
|
|||
pub fn resolve(
|
||||
&mut self,
|
||||
name: &Multiname<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Option<Value<'gc>>, Error> {
|
||||
if let Some(qname) = self.locals().resolve_multiname(name)? {
|
||||
if self.locals().has_property(&qname)? {
|
||||
|
@ -132,15 +129,14 @@ impl<'gc> Scope<'gc> {
|
|||
self.values,
|
||||
&qname,
|
||||
activation,
|
||||
context,
|
||||
)?));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(parent) = self.parent {
|
||||
return parent
|
||||
.write(context.gc_context)
|
||||
.resolve(name, activation, context);
|
||||
.write(activation.context.gc_context)
|
||||
.resolve(name, activation);
|
||||
}
|
||||
|
||||
//TODO: Should undefined variables halt execution?
|
||||
|
|
|
@ -14,7 +14,6 @@ use crate::avm2::slot::Slot;
|
|||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
|
@ -80,15 +79,14 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
|||
self,
|
||||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let rv = self
|
||||
.0
|
||||
.read()
|
||||
.get_property_local(reciever, name, activation)?;
|
||||
|
||||
rv.resolve(activation, context)
|
||||
rv.resolve(activation)
|
||||
}
|
||||
|
||||
fn set_property_local(
|
||||
|
@ -96,15 +94,14 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let rv = self
|
||||
.0
|
||||
.write(context.gc_context)
|
||||
.set_property_local(reciever, name, value, activation, context)?;
|
||||
.write(activation.context.gc_context)
|
||||
.set_property_local(reciever, name, value, activation)?;
|
||||
|
||||
rv.resolve(activation, context)?;
|
||||
rv.resolve(activation)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -114,15 +111,14 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let rv = self
|
||||
.0
|
||||
.write(context.gc_context)
|
||||
.init_property_local(reciever, name, value, activation, context)?;
|
||||
.write(activation.context.gc_context)
|
||||
.init_property_local(reciever, name, value, activation)?;
|
||||
|
||||
rv.resolve(activation, context)?;
|
||||
rv.resolve(activation)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -245,24 +241,22 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
|||
|
||||
fn construct(
|
||||
&self,
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::ScriptObject(*self);
|
||||
Ok(ScriptObject::object(context.gc_context, this))
|
||||
Ok(ScriptObject::object(activation.context.gc_context, this))
|
||||
}
|
||||
|
||||
fn derive(
|
||||
&self,
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
class: GcCell<'gc, Class<'gc>>,
|
||||
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::ScriptObject(*self);
|
||||
Ok(ScriptObject::prototype(
|
||||
context.gc_context,
|
||||
activation.context.gc_context,
|
||||
this,
|
||||
class,
|
||||
scope,
|
||||
|
@ -419,7 +413,7 @@ impl<'gc> ScriptObjectData<'gc> {
|
|||
&self,
|
||||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<ReturnValue<'gc>, Error> {
|
||||
let prop = self.values.get(name);
|
||||
|
||||
|
@ -435,8 +429,7 @@ impl<'gc> ScriptObjectData<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<ReturnValue<'gc>, Error> {
|
||||
let slot_id = if let Some(prop) = self.values.get(name) {
|
||||
if let Some(slot_id) = prop.slot_id() {
|
||||
|
@ -449,7 +442,7 @@ impl<'gc> ScriptObjectData<'gc> {
|
|||
};
|
||||
|
||||
if let Some(slot_id) = slot_id {
|
||||
self.set_slot(slot_id, value, context.gc_context)?;
|
||||
self.set_slot(slot_id, value, activation.context.gc_context)?;
|
||||
Ok(Value::Undefined.into())
|
||||
} else if self.values.contains_key(name) {
|
||||
let prop = self.values.get_mut(name).unwrap();
|
||||
|
@ -470,12 +463,11 @@ impl<'gc> ScriptObjectData<'gc> {
|
|||
reciever: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<ReturnValue<'gc>, Error> {
|
||||
if let Some(prop) = self.values.get_mut(name) {
|
||||
if let Some(slot_id) = prop.slot_id() {
|
||||
self.init_slot(slot_id, value, context.gc_context)?;
|
||||
self.init_slot(slot_id, value, activation.context.gc_context)?;
|
||||
Ok(Value::Undefined.into())
|
||||
} else {
|
||||
let proto = self.proto;
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::avm1;
|
|||
|
||||
use crate::avm1::globals::system::SystemProperties;
|
||||
use crate::avm1::{Avm1, Object, Timers, Value};
|
||||
use crate::avm2::Avm2;
|
||||
use crate::backend::input::InputBackend;
|
||||
use crate::backend::storage::StorageBackend;
|
||||
use crate::backend::{audio::AudioBackend, navigator::NavigatorBackend, render::RenderBackend};
|
||||
|
@ -117,6 +118,9 @@ pub struct UpdateContext<'a, 'gc, 'gc_context> {
|
|||
|
||||
/// The AVM1 global state.
|
||||
pub avm1: &'a mut Avm1<'gc>,
|
||||
|
||||
/// The AVM2 global state.
|
||||
pub avm2: &'a mut Avm2<'gc>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, 'gc, 'gc_context> Collect for UpdateContext<'a, 'gc, 'gc_context> {
|
||||
|
@ -145,6 +149,7 @@ unsafe impl<'a, 'gc, 'gc_context> Collect for UpdateContext<'a, 'gc, 'gc_context
|
|||
self.unbound_text_fields.trace(cc);
|
||||
self.timers.trace(cc);
|
||||
self.avm1.trace(cc);
|
||||
self.avm2.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,6 +193,7 @@ impl<'a, 'gc, 'gc_context> UpdateContext<'a, 'gc, 'gc_context> {
|
|||
unbound_text_fields: self.unbound_text_fields,
|
||||
timers: self.timers,
|
||||
avm1: self.avm1,
|
||||
avm2: self.avm2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,13 +370,14 @@ impl<'gc> Loader<'gc> {
|
|||
.expect("Could not upgrade weak reference to player");
|
||||
|
||||
Box::pin(async move {
|
||||
player.lock().expect("Could not lock player!!").update(
|
||||
|_avm2, uc| -> Result<(), Error> {
|
||||
player
|
||||
.lock()
|
||||
.expect("Could not lock player!!")
|
||||
.update(|uc| -> Result<(), Error> {
|
||||
url = uc.navigator.resolve_relative_url(&url).into_owned();
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
let data = (fetch.await)
|
||||
.and_then(|data| Ok((data.len(), SwfMovie::from_data(&data, Some(url.clone()))?)));
|
||||
|
@ -414,8 +415,10 @@ impl<'gc> Loader<'gc> {
|
|||
.expect("Could not upgrade weak reference to player");
|
||||
|
||||
Box::pin(async move {
|
||||
player.lock().expect("Could not lock player!!").update(
|
||||
|_avm2, uc| -> Result<(), Error> {
|
||||
player
|
||||
.lock()
|
||||
.expect("Could not lock player!!")
|
||||
.update(|uc| -> Result<(), Error> {
|
||||
url = uc.navigator.resolve_relative_url(&url).into_owned();
|
||||
|
||||
let (clip, broadcaster) = match uc.load_manager.get_loader(handle) {
|
||||
|
@ -446,8 +449,7 @@ impl<'gc> Loader<'gc> {
|
|||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
let data = (fetch.await)
|
||||
.and_then(|data| Ok((data.len(), SwfMovie::from_data(&data, Some(url.clone()))?)));
|
||||
|
@ -457,7 +459,7 @@ impl<'gc> Loader<'gc> {
|
|||
player
|
||||
.lock()
|
||||
.expect("Could not lock player!!")
|
||||
.update(|_avm2, uc| {
|
||||
.update(|uc| {
|
||||
let (clip, broadcaster) = match uc.load_manager.get_loader(handle) {
|
||||
Some(Loader::Movie {
|
||||
target_clip,
|
||||
|
@ -530,8 +532,10 @@ impl<'gc> Loader<'gc> {
|
|||
//error types we can actually inspect.
|
||||
//This also can get errors from decoding an invalid SWF file,
|
||||
//too. We should distinguish those to player code.
|
||||
player.lock().expect("Could not lock player!!").update(
|
||||
|_avm2, uc| -> Result<(), Error> {
|
||||
player
|
||||
.lock()
|
||||
.expect("Could not lock player!!")
|
||||
.update(|uc| -> Result<(), Error> {
|
||||
let (clip, broadcaster) = match uc.load_manager.get_loader(handle) {
|
||||
Some(Loader::Movie {
|
||||
target_clip,
|
||||
|
@ -564,8 +568,7 @@ impl<'gc> Loader<'gc> {
|
|||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -588,7 +591,7 @@ impl<'gc> Loader<'gc> {
|
|||
let data = fetch.await?;
|
||||
|
||||
// Fire the load handler.
|
||||
player.lock().unwrap().update(|_avm2, uc| {
|
||||
player.lock().unwrap().update(|uc| {
|
||||
let loader = uc.load_manager.get_loader(handle);
|
||||
let that = match loader {
|
||||
Some(&Loader::Form { target_object, .. }) => target_object,
|
||||
|
@ -635,7 +638,7 @@ impl<'gc> Loader<'gc> {
|
|||
let data = fetch.await;
|
||||
|
||||
// Fire the load handler.
|
||||
player.lock().unwrap().update(|_avm2, uc| {
|
||||
player.lock().unwrap().update(|uc| {
|
||||
let loader = uc.load_manager.get_loader(handle);
|
||||
let that = match loader {
|
||||
Some(&Loader::LoadVars { target_object, .. }) => target_object,
|
||||
|
@ -737,7 +740,7 @@ impl<'gc> Loader<'gc> {
|
|||
let xmlstring = String::from_utf8(data)?;
|
||||
|
||||
player.lock().expect("Could not lock player!!").update(
|
||||
|_avm2, uc| -> Result<(), Error> {
|
||||
|uc| -> Result<(), Error> {
|
||||
let (mut node, active_clip) = match uc.load_manager.get_loader(handle) {
|
||||
Some(Loader::XML {
|
||||
target_node,
|
||||
|
@ -773,7 +776,7 @@ impl<'gc> Loader<'gc> {
|
|||
)?;
|
||||
} else {
|
||||
player.lock().expect("Could not lock player!!").update(
|
||||
|_avm2, uc| -> Result<(), Error> {
|
||||
|uc| -> Result<(), Error> {
|
||||
let (mut node, active_clip) = match uc.load_manager.get_loader(handle) {
|
||||
Some(Loader::XML {
|
||||
target_node,
|
||||
|
|
|
@ -275,7 +275,7 @@ impl Player {
|
|||
/// This should not be called if a root movie fetch has already been kicked
|
||||
/// off.
|
||||
pub fn fetch_root_movie(&mut self, movie_url: &str) {
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let fetch = context.navigator.fetch(movie_url, RequestOptions::get());
|
||||
let process = context.load_manager.load_root_movie(
|
||||
context.player.clone().unwrap(),
|
||||
|
@ -305,7 +305,7 @@ impl Player {
|
|||
self.frame_rate = movie.header().frame_rate.into();
|
||||
self.swf = movie;
|
||||
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let mut root: DisplayObject =
|
||||
MovieClip::from_movie(context.gc_context, context.swf.clone()).into();
|
||||
root.set_depth(context.gc_context, 0);
|
||||
|
@ -447,7 +447,7 @@ impl Player {
|
|||
{
|
||||
if self.input.is_key_down(KeyCode::Control) && self.input.is_key_down(KeyCode::Alt)
|
||||
{
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let mut dumper = VariableDumper::new(" ");
|
||||
let levels = context.levels.clone();
|
||||
|
||||
|
@ -483,19 +483,19 @@ impl Player {
|
|||
{
|
||||
if self.input.is_key_down(KeyCode::Control) && self.input.is_key_down(KeyCode::Alt)
|
||||
{
|
||||
self.mutate_with_update_context(|avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
if context.avm1.show_debug_output() {
|
||||
log::info!(
|
||||
"AVM Debugging turned off! Press CTRL+ALT+D to turn off again."
|
||||
);
|
||||
context.avm1.set_show_debug_output(false);
|
||||
avm2.set_show_debug_output(false);
|
||||
context.avm2.set_show_debug_output(false);
|
||||
} else {
|
||||
log::info!(
|
||||
"AVM Debugging turned on! Press CTRL+ALT+D to turn on again."
|
||||
);
|
||||
context.avm1.set_show_debug_output(true);
|
||||
avm2.set_show_debug_output(true);
|
||||
context.avm2.set_show_debug_output(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ impl Player {
|
|||
};
|
||||
|
||||
if button_event.is_some() {
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let levels: Vec<DisplayObject<'_>> = context.levels.values().copied().collect();
|
||||
for level in levels {
|
||||
if let Some(button_event) = button_event {
|
||||
|
@ -565,7 +565,7 @@ impl Player {
|
|||
};
|
||||
|
||||
if clip_event.is_some() || listener.is_some() {
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let levels: Vec<DisplayObject<'_>> = context.levels.values().copied().collect();
|
||||
|
||||
for level in levels {
|
||||
|
@ -589,7 +589,7 @@ impl Player {
|
|||
}
|
||||
|
||||
let mut is_mouse_down = self.is_mouse_down;
|
||||
self.mutate_with_update_context(|avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
if let Some(node) = context.mouse_hovered_object {
|
||||
if node.removed() {
|
||||
context.mouse_hovered_object = None;
|
||||
|
@ -616,7 +616,7 @@ impl Player {
|
|||
_ => (),
|
||||
}
|
||||
|
||||
Self::run_actions(avm2, context);
|
||||
Self::run_actions(context);
|
||||
});
|
||||
self.is_mouse_down = is_mouse_down;
|
||||
if needs_render {
|
||||
|
@ -627,7 +627,7 @@ impl Player {
|
|||
/// Update dragged object, if any.
|
||||
fn update_drag(&mut self) {
|
||||
let mouse_pos = self.mouse_pos;
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
if let Some(drag_object) = &mut context.drag_object {
|
||||
if drag_object.display_object.removed() {
|
||||
// Be sure to clear the drag if the object was removed.
|
||||
|
@ -662,7 +662,7 @@ impl Player {
|
|||
let mouse_pos = self.mouse_pos;
|
||||
|
||||
let mut new_cursor = self.mouse_cursor;
|
||||
let hover_changed = self.mutate_with_update_context(|avm2, context| {
|
||||
let hover_changed = self.mutate_with_update_context(|context| {
|
||||
// Check hovered object.
|
||||
let mut new_hovered = None;
|
||||
for (_depth, level) in context.levels.clone().iter().rev() {
|
||||
|
@ -692,7 +692,7 @@ impl Player {
|
|||
|
||||
context.mouse_hovered_object = new_hovered;
|
||||
|
||||
Self::run_actions(avm2, context);
|
||||
Self::run_actions(context);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -713,7 +713,7 @@ impl Player {
|
|||
/// This should only be called once. Further movie loads should preload the
|
||||
/// specific `MovieClip` referenced.
|
||||
fn preload(&mut self) {
|
||||
self.mutate_with_update_context(|_avm2, context| {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let mut morph_shapes = fnv::FnvHashMap::default();
|
||||
let root = *context.levels.get(&0).expect("root level");
|
||||
root.as_movie_clip()
|
||||
|
@ -732,7 +732,7 @@ impl Player {
|
|||
}
|
||||
|
||||
pub fn run_frame(&mut self) {
|
||||
self.update(|_avm2, update_context| {
|
||||
self.update(|update_context| {
|
||||
// TODO: In what order are levels run?
|
||||
// NOTE: We have to copy all the layer pointers into a separate list
|
||||
// because level updates can create more levels, which we don't
|
||||
|
@ -813,7 +813,7 @@ impl Player {
|
|||
self.input.deref_mut()
|
||||
}
|
||||
|
||||
fn run_actions<'gc>(avm2: &mut Avm2<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
fn run_actions<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
// Note that actions can queue further actions, so a while loop is necessary here.
|
||||
while let Some(actions) = context.action_queue.pop_action() {
|
||||
// We don't run frame actions if the clip was removed after it queued the action.
|
||||
|
@ -917,7 +917,7 @@ impl Player {
|
|||
is_lazy_initialize,
|
||||
abc,
|
||||
} => {
|
||||
if let Err(e) = avm2.load_abc(abc, &name, is_lazy_initialize, context) {
|
||||
if let Err(e) = Avm2::load_abc(abc, &name, is_lazy_initialize, context) {
|
||||
log::warn!("Error loading ABC file: {}", e);
|
||||
}
|
||||
}
|
||||
|
@ -966,7 +966,7 @@ impl Player {
|
|||
/// This takes cares of populating the `UpdateContext` struct, avoiding borrow issues.
|
||||
fn mutate_with_update_context<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: for<'a, 'gc> FnOnce(&mut Avm2<'gc>, &mut UpdateContext<'a, 'gc, '_>) -> R,
|
||||
F: for<'a, 'gc> FnOnce(&mut UpdateContext<'a, 'gc, '_>) -> R,
|
||||
{
|
||||
// We have to do this piecewise borrowing of fields before the closure to avoid
|
||||
// completely borrowing `self`.
|
||||
|
@ -1050,9 +1050,10 @@ impl Player {
|
|||
timers,
|
||||
needs_render,
|
||||
avm1,
|
||||
avm2,
|
||||
};
|
||||
|
||||
let ret = f(avm2, &mut update_context);
|
||||
let ret = f(&mut update_context);
|
||||
|
||||
// Hovered object may have been updated; copy it back to the GC root.
|
||||
root_data.mouse_hovered_object = update_context.mouse_hovered_object;
|
||||
|
@ -1084,15 +1085,12 @@ impl Player {
|
|||
/// hover state up to date, and running garbage collection.
|
||||
pub fn update<F, R>(&mut self, func: F) -> R
|
||||
where
|
||||
F: for<'a, 'gc, 'gc_context> FnOnce(
|
||||
&mut Avm2<'gc>,
|
||||
&mut UpdateContext<'a, 'gc, 'gc_context>,
|
||||
) -> R,
|
||||
F: for<'a, 'gc, 'gc_context> FnOnce(&mut UpdateContext<'a, 'gc, 'gc_context>) -> R,
|
||||
{
|
||||
let rval = self.mutate_with_update_context(|avm2, context| {
|
||||
let rval = func(avm2, context);
|
||||
let rval = self.mutate_with_update_context(|context| {
|
||||
let rval = func(context);
|
||||
|
||||
Self::run_actions(avm2, context);
|
||||
Self::run_actions(context);
|
||||
|
||||
rval
|
||||
});
|
||||
|
@ -1108,7 +1106,7 @@ impl Player {
|
|||
}
|
||||
|
||||
pub fn flush_shared_objects(&mut self) {
|
||||
self.update(|_avm2, context| {
|
||||
self.update(|context| {
|
||||
let mut activation =
|
||||
Activation::from_stub(context.reborrow(), ActivationIdentifier::root("[Flush]"));
|
||||
let shared_objects = activation.context.shared_objects.clone();
|
||||
|
@ -1122,7 +1120,7 @@ impl Player {
|
|||
/// Returns the approximate amount of time until the next timer tick.
|
||||
pub fn update_timers(&mut self, dt: f64) {
|
||||
self.time_til_next_timer =
|
||||
self.mutate_with_update_context(|_avm2, context| Timers::update_timers(context, dt));
|
||||
self.mutate_with_update_context(|context| Timers::update_timers(context, dt));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue