avm2: Add Loader Info class & object type
This commit is contained in:
parent
e2f124ee34
commit
60c92dde49
|
@ -710,6 +710,11 @@ pub fn load_player_globals<'gc>(
|
||||||
activation,
|
activation,
|
||||||
flash::display::capsstyle::create_class(mc),
|
flash::display::capsstyle::create_class(mc),
|
||||||
implicit_deriver,
|
implicit_deriver,
|
||||||
|
)?;
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
flash::display::loaderinfo::create_class(mc),
|
||||||
|
flash::display::loaderinfo::loaderinfo_deriver,
|
||||||
domain,
|
domain,
|
||||||
script,
|
script,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub mod graphics;
|
||||||
pub mod interactiveobject;
|
pub mod interactiveobject;
|
||||||
pub mod jointstyle;
|
pub mod jointstyle;
|
||||||
pub mod linescalemode;
|
pub mod linescalemode;
|
||||||
|
pub mod loaderinfo;
|
||||||
pub mod movieclip;
|
pub mod movieclip;
|
||||||
pub mod scene;
|
pub mod scene;
|
||||||
pub mod shape;
|
pub mod shape;
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
//! `flash.display.LoaderInfo` builtin/prototype
|
||||||
|
|
||||||
|
use crate::avm2::activation::Activation;
|
||||||
|
use crate::avm2::class::{Class, ClassAttributes};
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::{LoaderInfoObject, Object};
|
||||||
|
use crate::avm2::scope::Scope;
|
||||||
|
use crate::avm2::value::Value;
|
||||||
|
use crate::avm2::Error;
|
||||||
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
|
/// Implements `flash.display.LoaderInfo`'s instance constructor.
|
||||||
|
pub fn instance_init<'gc>(
|
||||||
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
Err("LoaderInfo cannot be constructed".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `flash.display.LoaderInfo`'s class constructor.
|
||||||
|
pub fn class_init<'gc>(
|
||||||
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derive `LoaderInfoObject` impls.
|
||||||
|
pub fn loaderinfo_deriver<'gc>(
|
||||||
|
base_proto: Object<'gc>,
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
class: GcCell<'gc, Class<'gc>>,
|
||||||
|
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||||
|
) -> Result<Object<'gc>, Error> {
|
||||||
|
LoaderInfoObject::derive(base_proto, activation.context.gc_context, class, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct `LoaderInfo`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
let class = Class::new(
|
||||||
|
QName::new(Namespace::package("flash.display"), "LoaderInfo"),
|
||||||
|
Some(QName::new(Namespace::package("flash.events"), "EventDispatcher").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut write = class.write(mc);
|
||||||
|
|
||||||
|
write.set_attributes(ClassAttributes::SEALED);
|
||||||
|
|
||||||
|
class
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ mod dispatch_object;
|
||||||
mod domain_object;
|
mod domain_object;
|
||||||
mod event_object;
|
mod event_object;
|
||||||
mod function_object;
|
mod function_object;
|
||||||
|
mod loaderinfo_object;
|
||||||
mod namespace_object;
|
mod namespace_object;
|
||||||
mod primitive_object;
|
mod primitive_object;
|
||||||
mod regexp_object;
|
mod regexp_object;
|
||||||
|
@ -40,6 +41,7 @@ pub use crate::avm2::object::dispatch_object::DispatchObject;
|
||||||
pub use crate::avm2::object::domain_object::DomainObject;
|
pub use crate::avm2::object::domain_object::DomainObject;
|
||||||
pub use crate::avm2::object::event_object::EventObject;
|
pub use crate::avm2::object::event_object::EventObject;
|
||||||
pub use crate::avm2::object::function_object::{implicit_deriver, FunctionObject};
|
pub use crate::avm2::object::function_object::{implicit_deriver, FunctionObject};
|
||||||
|
pub use crate::avm2::object::loaderinfo_object::LoaderInfoObject;
|
||||||
pub use crate::avm2::object::namespace_object::NamespaceObject;
|
pub use crate::avm2::object::namespace_object::NamespaceObject;
|
||||||
pub use crate::avm2::object::primitive_object::PrimitiveObject;
|
pub use crate::avm2::object::primitive_object::PrimitiveObject;
|
||||||
pub use crate::avm2::object::regexp_object::RegExpObject;
|
pub use crate::avm2::object::regexp_object::RegExpObject;
|
||||||
|
@ -64,7 +66,8 @@ pub use crate::avm2::object::xml_object::XmlObject;
|
||||||
DispatchObject(DispatchObject<'gc>),
|
DispatchObject(DispatchObject<'gc>),
|
||||||
XmlObject(XmlObject<'gc>),
|
XmlObject(XmlObject<'gc>),
|
||||||
RegExpObject(RegExpObject<'gc>),
|
RegExpObject(RegExpObject<'gc>),
|
||||||
ByteArrayObject(ByteArrayObject<'gc>)
|
ByteArrayObject(ByteArrayObject<'gc>),
|
||||||
|
LoaderInfoObject(LoaderInfoObject<'gc>),
|
||||||
}
|
}
|
||||||
)]
|
)]
|
||||||
pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy {
|
pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy {
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
//! Loader-info object
|
||||||
|
|
||||||
|
use crate::avm2::activation::Activation;
|
||||||
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::script_object::{ScriptObjectClass, ScriptObjectData};
|
||||||
|
use crate::avm2::object::{Object, ObjectPtr, TObject};
|
||||||
|
use crate::avm2::scope::Scope;
|
||||||
|
use crate::avm2::string::AvmString;
|
||||||
|
use crate::avm2::traits::Trait;
|
||||||
|
use crate::avm2::value::Value;
|
||||||
|
use crate::avm2::Error;
|
||||||
|
use crate::tag_utils::SwfMovie;
|
||||||
|
use crate::{impl_avm2_custom_object, impl_avm2_custom_object_properties};
|
||||||
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Represents a thing which can be loaded by a loader.
|
||||||
|
#[derive(Collect, Debug, Clone)]
|
||||||
|
#[collect(no_drop)]
|
||||||
|
pub enum LoaderStream {
|
||||||
|
/// A loaded SWF movie.
|
||||||
|
SWF(Arc<SwfMovie>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An Object which represents a loadable object, such as a SWF movie or image
|
||||||
|
/// resource.
|
||||||
|
#[derive(Collect, Debug, Clone, Copy)]
|
||||||
|
#[collect(no_drop)]
|
||||||
|
pub struct LoaderInfoObject<'gc>(GcCell<'gc, LoaderInfoObjectData<'gc>>);
|
||||||
|
|
||||||
|
#[derive(Collect, Debug, Clone)]
|
||||||
|
#[collect(no_drop)]
|
||||||
|
pub struct LoaderInfoObjectData<'gc> {
|
||||||
|
/// All normal script data.
|
||||||
|
base: ScriptObjectData<'gc>,
|
||||||
|
|
||||||
|
/// The loaded stream that this gets it's info from.
|
||||||
|
loaded_stream: Option<LoaderStream>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gc> LoaderInfoObject<'gc> {
|
||||||
|
/// Box a movie into a loader info object.
|
||||||
|
pub fn from_movie(
|
||||||
|
movie: Arc<SwfMovie>,
|
||||||
|
base_proto: Object<'gc>,
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
) -> Result<Object<'gc>, Error> {
|
||||||
|
let base = ScriptObjectData::base_new(Some(base_proto), ScriptObjectClass::NoClass);
|
||||||
|
let loaded_stream = Some(LoaderStream::SWF(movie));
|
||||||
|
|
||||||
|
Ok(LoaderInfoObject(GcCell::allocate(
|
||||||
|
mc,
|
||||||
|
LoaderInfoObjectData {
|
||||||
|
base,
|
||||||
|
loaded_stream,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a loader-info subclass.
|
||||||
|
pub fn derive(
|
||||||
|
base_proto: Object<'gc>,
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
class: GcCell<'gc, Class<'gc>>,
|
||||||
|
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||||
|
) -> Result<Object<'gc>, Error> {
|
||||||
|
let base = ScriptObjectData::base_new(
|
||||||
|
Some(base_proto),
|
||||||
|
ScriptObjectClass::InstancePrototype(class, scope),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(LoaderInfoObject(GcCell::allocate(
|
||||||
|
mc,
|
||||||
|
LoaderInfoObjectData {
|
||||||
|
base,
|
||||||
|
loaded_stream: None,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gc> TObject<'gc> for LoaderInfoObject<'gc> {
|
||||||
|
impl_avm2_custom_object!(base);
|
||||||
|
impl_avm2_custom_object_properties!(base);
|
||||||
|
|
||||||
|
fn value_of(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
|
||||||
|
if let Some(class) = self.as_proto_class() {
|
||||||
|
Ok(AvmString::new(mc, format!("[object {}]", class.read().name().local_name())).into())
|
||||||
|
} else {
|
||||||
|
Ok("[object Object]".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn construct(
|
||||||
|
&self,
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Object<'gc>, Error> {
|
||||||
|
let this: Object<'gc> = Object::LoaderInfoObject(*self);
|
||||||
|
let base = ScriptObjectData::base_new(Some(this), ScriptObjectClass::NoClass);
|
||||||
|
|
||||||
|
Ok(LoaderInfoObject(GcCell::allocate(
|
||||||
|
activation.context.gc_context,
|
||||||
|
LoaderInfoObjectData {
|
||||||
|
base,
|
||||||
|
loaded_stream: None,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive(
|
||||||
|
&self,
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
class: GcCell<'gc, Class<'gc>>,
|
||||||
|
scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||||
|
) -> Result<Object<'gc>, Error> {
|
||||||
|
let this: Object<'gc> = Object::LoaderInfoObject(*self);
|
||||||
|
let base = ScriptObjectData::base_new(
|
||||||
|
Some(this),
|
||||||
|
ScriptObjectClass::InstancePrototype(class, scope),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(LoaderInfoObject(GcCell::allocate(
|
||||||
|
activation.context.gc_context,
|
||||||
|
LoaderInfoObjectData {
|
||||||
|
base,
|
||||||
|
loaded_stream: None,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue