Convert our stub implementations of all non-ECMA classes into `Class`es.
This was surprisingly tricky - due to the need to look up superclasses, class trait instantiation requires an active `Activation` and `UpdateContext`. We can't get those during VM instance creation, since the player needs the VM first before it can give it a context to work with. Ergo, we have to tear the global scope initialization in two. At the first possible moment, the player calls a new `load_player_globals` method that initializes all class traits in global scope.
This commit is contained in:
parent
6f284f60eb
commit
3585cf983b
|
@ -77,6 +77,11 @@ impl<'gc> Avm2<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_player_globals(context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
|
let mut activation = Activation::from_nothing(context.reborrow());
|
||||||
|
globals::load_player_globals(&mut activation)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the current set of system prototypes.
|
/// Return the current set of system prototypes.
|
||||||
pub fn prototypes(&self) -> &SystemPrototypes<'gc> {
|
pub fn prototypes(&self) -> &SystemPrototypes<'gc> {
|
||||||
&self.system_prototypes
|
&self.system_prototypes
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
//! Global scope built-ins
|
//! Global scope built-ins
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
|
use crate::avm2::class::Class;
|
||||||
use crate::avm2::method::NativeMethod;
|
use crate::avm2::method::NativeMethod;
|
||||||
use crate::avm2::names::{Namespace, QName};
|
use crate::avm2::names::{Namespace, QName};
|
||||||
use crate::avm2::object::{FunctionObject, ScriptObject};
|
use crate::avm2::object::{FunctionObject, Object, ScriptObject, TObject};
|
||||||
use crate::avm2::object::{Object, TObject};
|
use crate::avm2::r#trait::Trait;
|
||||||
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 gc_arena::{Collect, MutationContext};
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
use std::f64::NAN;
|
use std::f64::NAN;
|
||||||
|
|
||||||
mod boolean;
|
mod boolean;
|
||||||
|
@ -67,8 +68,8 @@ fn function<'gc>(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a class builtin to the global scope.
|
/// Add an ES3-style builtin to the global scope.
|
||||||
fn class<'gc>(
|
fn oldstyle_class<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
mc: MutationContext<'gc, '_>,
|
||||||
mut global_scope: Object<'gc>,
|
mut global_scope: Object<'gc>,
|
||||||
package: impl Into<AvmString<'gc>>,
|
package: impl Into<AvmString<'gc>>,
|
||||||
|
@ -88,6 +89,17 @@ fn class<'gc>(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a class builtin to the global scope.
|
||||||
|
fn class<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
mut global_scope: Object<'gc>,
|
||||||
|
class_def: GcCell<'gc, Class<'gc>>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let class_trait = Trait::from_class(class_def);
|
||||||
|
|
||||||
|
global_scope.install_trait(activation, class_trait, global_scope)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a builtin constant to the global scope.
|
/// Add a builtin constant to the global scope.
|
||||||
fn constant<'gc>(
|
fn constant<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
mc: MutationContext<'gc, '_>,
|
||||||
|
@ -103,6 +115,14 @@ fn constant<'gc>(
|
||||||
///
|
///
|
||||||
/// This function returns both the global scope object, as well as all builtin
|
/// This function returns both the global scope object, as well as all builtin
|
||||||
/// prototypes that other parts of the VM will need to use.
|
/// prototypes that other parts of the VM will need to use.
|
||||||
|
///
|
||||||
|
/// Due to a limitation of our type system and our garbage collector, the
|
||||||
|
/// player needs a valid `Avm2` but cannot provide us an `UpdateContext` yet.
|
||||||
|
/// As a result, global scope initialization is split into an "oldstyle phase"
|
||||||
|
/// and a "player-globals phase". This is the former phase, where we initialize
|
||||||
|
/// as much as we can without an `UpdateContext`. Note that not all
|
||||||
|
/// `SystemPrototypes` will be necessarily valid at this point in time, and
|
||||||
|
/// using them right away will result in objects of the wrong type.
|
||||||
pub fn construct_global_scope<'gc>(
|
pub fn construct_global_scope<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
mc: MutationContext<'gc, '_>,
|
||||||
) -> (Object<'gc>, SystemPrototypes<'gc>) {
|
) -> (Object<'gc>, SystemPrototypes<'gc>) {
|
||||||
|
@ -121,7 +141,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
|
|
||||||
object::fill_proto(mc, object_proto, fn_proto);
|
object::fill_proto(mc, object_proto, fn_proto);
|
||||||
|
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -130,7 +150,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
object_proto,
|
object_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -139,7 +159,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
fn_proto,
|
fn_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -148,7 +168,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
class_proto,
|
class_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -157,7 +177,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
string_proto,
|
string_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -166,7 +186,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
boolean_proto,
|
boolean_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -175,9 +195,9 @@ pub fn construct_global_scope<'gc>(
|
||||||
number_proto,
|
number_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
class(mc, gs, "", "int", int::constructor, int_proto, fn_proto);
|
oldstyle_class(mc, gs, "", "int", int::constructor, int_proto, fn_proto);
|
||||||
class(mc, gs, "", "uint", uint::constructor, uint_proto, fn_proto);
|
oldstyle_class(mc, gs, "", "uint", uint::constructor, uint_proto, fn_proto);
|
||||||
class(
|
oldstyle_class(
|
||||||
mc,
|
mc,
|
||||||
gs,
|
gs,
|
||||||
"",
|
"",
|
||||||
|
@ -192,77 +212,6 @@ pub fn construct_global_scope<'gc>(
|
||||||
constant(mc, gs, "", "NaN", NAN.into());
|
constant(mc, gs, "", "NaN", NAN.into());
|
||||||
constant(mc, gs, "", "Infinity", f64::INFINITY.into());
|
constant(mc, gs, "", "Infinity", f64::INFINITY.into());
|
||||||
|
|
||||||
// package `flash.events`
|
|
||||||
let eventdispatcher_proto =
|
|
||||||
flash::events::eventdispatcher::create_proto(mc, object_proto, fn_proto);
|
|
||||||
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.events",
|
|
||||||
"EventDispatcher",
|
|
||||||
flash::events::eventdispatcher::constructor,
|
|
||||||
eventdispatcher_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
|
|
||||||
// package `flash.display`
|
|
||||||
let displayobject_proto =
|
|
||||||
flash::display::displayobject::create_proto(mc, eventdispatcher_proto, fn_proto);
|
|
||||||
let interactiveobject_proto =
|
|
||||||
flash::display::interactiveobject::create_proto(mc, displayobject_proto, fn_proto);
|
|
||||||
let displayobjectcontainer_proto =
|
|
||||||
flash::display::displayobjectcontainer::create_proto(mc, interactiveobject_proto, fn_proto);
|
|
||||||
let sprite_proto =
|
|
||||||
flash::display::sprite::create_proto(mc, displayobjectcontainer_proto, fn_proto);
|
|
||||||
let movieclip_proto = flash::display::movieclip::create_proto(mc, sprite_proto, fn_proto);
|
|
||||||
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.display",
|
|
||||||
"DisplayObject",
|
|
||||||
flash::display::displayobject::constructor,
|
|
||||||
displayobject_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.display",
|
|
||||||
"InteractiveObject",
|
|
||||||
flash::display::interactiveobject::constructor,
|
|
||||||
interactiveobject_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.display",
|
|
||||||
"DisplayObjectContainer",
|
|
||||||
flash::display::displayobjectcontainer::constructor,
|
|
||||||
sprite_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.display",
|
|
||||||
"Sprite",
|
|
||||||
flash::display::sprite::constructor,
|
|
||||||
sprite_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
class(
|
|
||||||
mc,
|
|
||||||
gs,
|
|
||||||
"flash.display",
|
|
||||||
"MovieClip",
|
|
||||||
flash::display::movieclip::constructor,
|
|
||||||
movieclip_proto,
|
|
||||||
fn_proto,
|
|
||||||
);
|
|
||||||
|
|
||||||
let system_prototypes = SystemPrototypes {
|
let system_prototypes = SystemPrototypes {
|
||||||
object: object_proto,
|
object: object_proto,
|
||||||
function: fn_proto,
|
function: fn_proto,
|
||||||
|
@ -277,3 +226,49 @@ pub fn construct_global_scope<'gc>(
|
||||||
|
|
||||||
(gs, system_prototypes)
|
(gs, system_prototypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialize all remaining builtin classes.
|
||||||
|
///
|
||||||
|
/// Due to a limitation of our type system and our garbage collector, the
|
||||||
|
/// player needs a valid `Avm2` but cannot provide us an `UpdateContext` yet.
|
||||||
|
/// As a result, global scope initialization is split into an "oldstyle phase"
|
||||||
|
/// and a "player-globals phase". This is the latter phase.
|
||||||
|
pub fn load_player_globals<'gc>(activation: &mut Activation<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
|
let gs = activation.avm2().globals();
|
||||||
|
|
||||||
|
// package `flash.events`
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::events::eventdispatcher::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// package `flash.display`
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::display::displayobject::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::display::interactiveobject::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::display::displayobjectcontainer::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::display::sprite::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
flash::display::movieclip::create_class(activation.context.gc_context),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.display.DisplayObject` builtin/prototype
|
//! `flash.display.DisplayObject` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.display.DisplayObject`'s constructor.
|
/// Implements `flash.display.DisplayObject`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,22 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `DisplayObject.prototype`.
|
/// Implements `flash.display.DisplayObject`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `DisplayObject`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package("flash.display"), "DisplayObject"),
|
||||||
|
Some(QName::new(Namespace::package("flash.events"), "EventDispatcher").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.display.DisplayObjectContainer` builtin/prototype
|
//! `flash.display.DisplayObjectContainer` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.display.DisplayObjectContainer`'s constructor.
|
/// Implements `flash.display.DisplayObjectContainer`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,25 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `DisplayObjectContainer.prototype`.
|
/// Implements `flash.display.DisplayObjectContainer`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `DisplayObjectContainer`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(
|
||||||
|
Namespace::package("flash.display"),
|
||||||
|
"DisplayObjectContainer",
|
||||||
|
),
|
||||||
|
Some(QName::new(Namespace::package("flash.display"), "InteractiveObject").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.display.InteractiveObject` builtin/prototype
|
//! `flash.display.InteractiveObject` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.display.InteractiveObject`'s constructor.
|
/// Implements `flash.display.InteractiveObject`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,22 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `InteractiveObject.prototype`.
|
/// Implements `flash.display.InteractiveObject`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `InteractiveObject`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package("flash.display"), "InteractiveObject"),
|
||||||
|
Some(QName::new(Namespace::package("flash.display"), "DisplayObject").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.display.MovieClip` builtin/prototype
|
//! `flash.display.MovieClip` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.display.MovieClip`'s constructor.
|
/// Implements `flash.display.MovieClip`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,22 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `MovieClip.prototype`.
|
/// Implements `flash.display.MovieClip`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `MovieClip`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package("flash.display"), "MovieClip"),
|
||||||
|
Some(QName::new(Namespace::package("flash.display"), "Sprite").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.display.Sprite` builtin/prototype
|
//! `flash.display.Sprite` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.display.Sprite`'s constructor.
|
/// Implements `flash.display.Sprite`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,28 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `Sprite.prototype`.
|
/// Implements `flash.display.Sprite`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `Sprite`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package("flash.display"), "Sprite"),
|
||||||
|
Some(
|
||||||
|
QName::new(
|
||||||
|
Namespace::package("flash.display"),
|
||||||
|
"DisplayObjectContainer",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
//! `flash.events.EventDispatcher` builtin/prototype
|
//! `flash.events.EventDispatcher` builtin/prototype
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::{Object, ScriptObject};
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
/// Implements `flash.events.EventDispatcher`'s constructor.
|
/// Implements `flash.events.EventDispatcher`'s instance constructor.
|
||||||
pub fn constructor<'gc>(
|
pub fn instance_init<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
_this: Option<Object<'gc>>,
|
_this: Option<Object<'gc>>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -15,12 +18,22 @@ pub fn constructor<'gc>(
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `EventDispatcher.prototype`.
|
/// Implements `flash.events.EventDispatcher`'s class constructor.
|
||||||
pub fn create_proto<'gc>(
|
pub fn class_init<'gc>(
|
||||||
mc: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
super_proto: Object<'gc>,
|
_this: Option<Object<'gc>>,
|
||||||
_fn_proto: Object<'gc>,
|
_args: &[Value<'gc>],
|
||||||
) -> Object<'gc> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
// TODO: Use `StageObject` here.
|
Ok(Value::Undefined)
|
||||||
ScriptObject::object(mc, super_proto)
|
}
|
||||||
|
|
||||||
|
/// Construct `EventDispatcher`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package("flash.events"), "EventDispatcher"),
|
||||||
|
Some(QName::new(Namespace::public_namespace(), "Object").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,6 +345,10 @@ impl Player {
|
||||||
AvmString::new(activation.context.gc_context, version_string).into(),
|
AvmString::new(activation.context.gc_context, version_string).into(),
|
||||||
EnumSet::empty(),
|
EnumSet::empty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
drop(activation);
|
||||||
|
|
||||||
|
Avm2::load_player_globals(context).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
self.build_matrices();
|
self.build_matrices();
|
||||||
|
|
Loading…
Reference in New Issue