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