2020-02-12 19:58:33 +00:00
|
|
|
//! Global scope built-ins
|
|
|
|
|
2020-07-04 21:18:41 +00:00
|
|
|
use crate::avm2::activation::Activation;
|
2020-07-07 04:24:16 +00:00
|
|
|
use crate::avm2::class::Class;
|
2020-09-24 03:35:11 +00:00
|
|
|
use crate::avm2::domain::Domain;
|
2020-07-03 01:49:53 +00:00
|
|
|
use crate::avm2::method::NativeMethod;
|
2020-02-19 03:26:08 +00:00
|
|
|
use crate::avm2::names::{Namespace, QName};
|
2020-08-26 03:10:59 +00:00
|
|
|
use crate::avm2::object::{
|
2021-05-16 02:36:11 +00:00
|
|
|
ClassObject, DomainObject, FunctionObject, Object, ScriptObject, TObject,
|
2020-08-26 03:10:59 +00:00
|
|
|
};
|
2020-07-11 21:39:45 +00:00
|
|
|
use crate::avm2::scope::Scope;
|
2020-09-24 03:35:11 +00:00
|
|
|
use crate::avm2::script::Script;
|
2020-07-18 20:20:58 +00:00
|
|
|
use crate::avm2::string::AvmString;
|
2020-02-23 02:27:03 +00:00
|
|
|
use crate::avm2::value::Value;
|
2020-07-04 21:18:41 +00:00
|
|
|
use crate::avm2::Error;
|
2020-07-07 04:24:16 +00:00
|
|
|
use gc_arena::{Collect, GcCell, MutationContext};
|
2020-02-12 19:58:33 +00:00
|
|
|
|
2020-08-26 03:10:59 +00:00
|
|
|
mod array;
|
2020-07-17 02:33:26 +00:00
|
|
|
mod boolean;
|
2020-03-09 01:53:33 +00:00
|
|
|
mod class;
|
2020-02-23 00:12:33 +00:00
|
|
|
mod flash;
|
2020-02-19 03:26:08 +00:00
|
|
|
mod function;
|
2020-09-22 00:37:22 +00:00
|
|
|
mod global_scope;
|
2020-07-17 02:33:26 +00:00
|
|
|
mod int;
|
2020-11-10 23:43:44 +00:00
|
|
|
mod math;
|
2020-07-17 02:33:26 +00:00
|
|
|
mod namespace;
|
|
|
|
mod number;
|
2020-02-19 03:26:08 +00:00
|
|
|
mod object;
|
2021-02-11 07:56:21 +00:00
|
|
|
mod regexp;
|
2020-07-17 02:33:26 +00:00
|
|
|
mod string;
|
|
|
|
mod r#uint;
|
2021-01-15 22:35:10 +00:00
|
|
|
mod xml;
|
|
|
|
mod xml_list;
|
2020-02-19 03:26:08 +00:00
|
|
|
|
2020-12-22 04:43:32 +00:00
|
|
|
const NS_RUFFLE_INTERNAL: &str = "https://ruffle.rs/AS3/impl/";
|
|
|
|
|
2020-02-23 02:27:03 +00:00
|
|
|
fn trace<'gc>(
|
2020-06-24 03:34:06 +00:00
|
|
|
activation: &mut Activation<'_, 'gc, '_>,
|
2020-02-24 03:11:02 +00:00
|
|
|
_this: Option<Object<'gc>>,
|
2020-02-23 02:27:03 +00:00
|
|
|
args: &[Value<'gc>],
|
2020-07-04 21:18:41 +00:00
|
|
|
) -> Result<Value<'gc>, Error> {
|
2020-11-11 00:30:01 +00:00
|
|
|
let mut message = String::new();
|
|
|
|
if !args.is_empty() {
|
|
|
|
message.push_str(&args[0].clone().coerce_to_string(activation)?);
|
|
|
|
for arg in &args[1..] {
|
|
|
|
message.push(' ');
|
|
|
|
message.push_str(&arg.clone().coerce_to_string(activation)?);
|
|
|
|
}
|
2020-02-23 02:27:03 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 00:30:01 +00:00
|
|
|
activation.context.log.avm_trace(&message);
|
|
|
|
|
2020-07-04 21:18:41 +00:00
|
|
|
Ok(Value::Undefined)
|
2020-02-23 02:27:03 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 05:30:11 +00:00
|
|
|
fn is_finite<'gc>(
|
|
|
|
activation: &mut Activation<'_, 'gc, '_>,
|
|
|
|
_this: Option<Object<'gc>>,
|
|
|
|
args: &[Value<'gc>],
|
|
|
|
) -> Result<Value<'gc>, Error> {
|
|
|
|
if let Some(val) = args.get(0) {
|
|
|
|
Ok(val.coerce_to_number(activation)?.is_finite().into())
|
|
|
|
} else {
|
|
|
|
Ok(false.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-28 04:40:47 +00:00
|
|
|
fn is_nan<'gc>(
|
|
|
|
activation: &mut Activation<'_, 'gc, '_>,
|
|
|
|
_this: Option<Object<'gc>>,
|
|
|
|
args: &[Value<'gc>],
|
|
|
|
) -> Result<Value<'gc>, Error> {
|
|
|
|
if let Some(val) = args.get(0) {
|
|
|
|
Ok(val.coerce_to_number(activation)?.is_nan().into())
|
|
|
|
} else {
|
|
|
|
Ok(true.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 03:26:08 +00:00
|
|
|
/// This structure represents all system builtins' prototypes.
|
|
|
|
#[derive(Clone, Collect)]
|
|
|
|
#[collect(no_drop)]
|
|
|
|
pub struct SystemPrototypes<'gc> {
|
|
|
|
pub object: Object<'gc>,
|
|
|
|
pub function: Object<'gc>,
|
2020-03-09 01:53:33 +00:00
|
|
|
pub class: Object<'gc>,
|
2020-09-22 00:37:22 +00:00
|
|
|
pub global: Object<'gc>,
|
2020-07-17 02:33:26 +00:00
|
|
|
pub string: Object<'gc>,
|
|
|
|
pub boolean: Object<'gc>,
|
|
|
|
pub number: Object<'gc>,
|
|
|
|
pub int: Object<'gc>,
|
|
|
|
pub uint: Object<'gc>,
|
|
|
|
pub namespace: Object<'gc>,
|
2020-08-26 03:10:59 +00:00
|
|
|
pub array: Object<'gc>,
|
2020-10-06 01:21:13 +00:00
|
|
|
pub movieclip: Object<'gc>,
|
2020-09-18 00:58:36 +00:00
|
|
|
pub framelabel: Object<'gc>,
|
2020-09-19 02:05:16 +00:00
|
|
|
pub scene: Object<'gc>,
|
2020-09-27 00:21:11 +00:00
|
|
|
pub application_domain: Object<'gc>,
|
2020-12-09 01:48:11 +00:00
|
|
|
pub event: Object<'gc>,
|
2021-01-05 03:14:14 +00:00
|
|
|
pub video: Object<'gc>,
|
2021-01-15 22:35:10 +00:00
|
|
|
pub xml: Object<'gc>,
|
|
|
|
pub xml_list: Object<'gc>,
|
2021-01-22 01:16:23 +00:00
|
|
|
pub display_object: Object<'gc>,
|
2021-02-09 03:40:22 +00:00
|
|
|
pub shape: Object<'gc>,
|
2021-03-18 19:03:04 +00:00
|
|
|
pub point: Object<'gc>,
|
2021-02-14 03:53:29 +00:00
|
|
|
pub textfield: Object<'gc>,
|
2021-02-26 00:04:25 +00:00
|
|
|
pub textformat: Object<'gc>,
|
2021-02-11 00:25:27 +00:00
|
|
|
pub graphics: Object<'gc>,
|
2021-03-20 02:25:11 +00:00
|
|
|
pub loaderinfo: Object<'gc>,
|
2021-03-22 22:35:43 +00:00
|
|
|
pub bytearray: Object<'gc>,
|
2021-04-17 20:03:19 +00:00
|
|
|
pub stage: Object<'gc>,
|
2021-04-24 00:35:55 +00:00
|
|
|
pub sprite: Object<'gc>,
|
2021-04-24 01:15:37 +00:00
|
|
|
pub simplebutton: Object<'gc>,
|
2020-02-19 03:26:08 +00:00
|
|
|
}
|
|
|
|
|
2020-08-05 03:00:17 +00:00
|
|
|
impl<'gc> SystemPrototypes<'gc> {
|
|
|
|
/// Construct a minimal set of system prototypes necessary for
|
|
|
|
/// bootstrapping player globals.
|
|
|
|
///
|
|
|
|
/// All other system prototypes aside from the three given here will be set
|
|
|
|
/// to the empty object also handed to this function. It is the caller's
|
|
|
|
/// responsibility to instantiate each class and replace the empty object
|
|
|
|
/// with that.
|
|
|
|
fn new(
|
|
|
|
object: Object<'gc>,
|
|
|
|
function: Object<'gc>,
|
|
|
|
class: Object<'gc>,
|
|
|
|
empty: Object<'gc>,
|
|
|
|
) -> Self {
|
|
|
|
SystemPrototypes {
|
|
|
|
object,
|
|
|
|
function,
|
|
|
|
class,
|
2020-09-22 00:37:22 +00:00
|
|
|
global: empty,
|
2020-08-05 03:00:17 +00:00
|
|
|
string: empty,
|
|
|
|
boolean: empty,
|
|
|
|
number: empty,
|
|
|
|
int: empty,
|
|
|
|
uint: empty,
|
|
|
|
namespace: empty,
|
2020-08-26 03:10:59 +00:00
|
|
|
array: empty,
|
2020-10-06 01:21:13 +00:00
|
|
|
movieclip: empty,
|
2020-09-18 00:58:36 +00:00
|
|
|
framelabel: empty,
|
2020-09-19 02:05:16 +00:00
|
|
|
scene: empty,
|
2020-09-27 00:21:11 +00:00
|
|
|
application_domain: empty,
|
2020-12-09 01:48:11 +00:00
|
|
|
event: empty,
|
2021-01-05 03:14:14 +00:00
|
|
|
video: empty,
|
2021-01-15 22:35:10 +00:00
|
|
|
xml: empty,
|
|
|
|
xml_list: empty,
|
2021-01-22 01:16:23 +00:00
|
|
|
display_object: empty,
|
2021-02-09 03:40:22 +00:00
|
|
|
shape: empty,
|
2021-03-18 19:03:04 +00:00
|
|
|
point: empty,
|
2021-02-14 03:53:29 +00:00
|
|
|
textfield: empty,
|
2021-02-26 00:04:25 +00:00
|
|
|
textformat: empty,
|
2021-02-11 00:25:27 +00:00
|
|
|
graphics: empty,
|
2021-03-20 02:25:11 +00:00
|
|
|
loaderinfo: empty,
|
2021-03-22 22:35:43 +00:00
|
|
|
bytearray: empty,
|
2021-04-17 20:03:19 +00:00
|
|
|
stage: empty,
|
2021-04-24 00:35:55 +00:00
|
|
|
sprite: empty,
|
2021-04-24 01:15:37 +00:00
|
|
|
simplebutton: empty,
|
2020-08-05 03:00:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
/// This structure represents all system builtins' constructors.
|
|
|
|
#[derive(Clone, Collect)]
|
|
|
|
#[collect(no_drop)]
|
|
|
|
pub struct SystemConstructors<'gc> {
|
|
|
|
pub object: Object<'gc>,
|
|
|
|
pub function: Object<'gc>,
|
|
|
|
pub class: Object<'gc>,
|
|
|
|
pub global: Object<'gc>,
|
|
|
|
pub string: Object<'gc>,
|
|
|
|
pub boolean: Object<'gc>,
|
|
|
|
pub number: Object<'gc>,
|
|
|
|
pub int: Object<'gc>,
|
|
|
|
pub uint: Object<'gc>,
|
|
|
|
pub namespace: Object<'gc>,
|
|
|
|
pub array: Object<'gc>,
|
|
|
|
pub movieclip: Object<'gc>,
|
|
|
|
pub framelabel: Object<'gc>,
|
|
|
|
pub scene: Object<'gc>,
|
|
|
|
pub application_domain: Object<'gc>,
|
|
|
|
pub event: Object<'gc>,
|
|
|
|
pub video: Object<'gc>,
|
|
|
|
pub xml: Object<'gc>,
|
|
|
|
pub xml_list: Object<'gc>,
|
|
|
|
pub display_object: Object<'gc>,
|
|
|
|
pub shape: Object<'gc>,
|
|
|
|
pub point: Object<'gc>,
|
|
|
|
pub textfield: Object<'gc>,
|
|
|
|
pub textformat: Object<'gc>,
|
|
|
|
pub graphics: Object<'gc>,
|
|
|
|
pub loaderinfo: Object<'gc>,
|
|
|
|
pub bytearray: Object<'gc>,
|
|
|
|
pub stage: Object<'gc>,
|
|
|
|
pub sprite: Object<'gc>,
|
|
|
|
pub simplebutton: Object<'gc>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'gc> SystemConstructors<'gc> {
|
|
|
|
/// Construct a minimal set of system prototypes necessary for
|
|
|
|
/// bootstrapping player globals.
|
|
|
|
///
|
|
|
|
/// All other system prototypes aside from the three given here will be set
|
|
|
|
/// to the empty object also handed to this function. It is the caller's
|
|
|
|
/// responsibility to instantiate each class and replace the empty object
|
|
|
|
/// with that.
|
|
|
|
fn new(
|
|
|
|
object: Object<'gc>,
|
|
|
|
function: Object<'gc>,
|
|
|
|
class: Object<'gc>,
|
|
|
|
empty: Object<'gc>,
|
|
|
|
) -> Self {
|
|
|
|
SystemConstructors {
|
|
|
|
object,
|
|
|
|
function,
|
|
|
|
class,
|
|
|
|
global: empty,
|
|
|
|
string: empty,
|
|
|
|
boolean: empty,
|
|
|
|
number: empty,
|
|
|
|
int: empty,
|
|
|
|
uint: empty,
|
|
|
|
namespace: empty,
|
|
|
|
array: empty,
|
|
|
|
movieclip: empty,
|
|
|
|
framelabel: empty,
|
|
|
|
scene: empty,
|
|
|
|
application_domain: empty,
|
|
|
|
event: empty,
|
|
|
|
video: empty,
|
|
|
|
xml: empty,
|
|
|
|
xml_list: empty,
|
|
|
|
display_object: empty,
|
|
|
|
shape: empty,
|
|
|
|
point: empty,
|
|
|
|
textfield: empty,
|
|
|
|
textformat: empty,
|
|
|
|
graphics: empty,
|
|
|
|
loaderinfo: empty,
|
|
|
|
bytearray: empty,
|
|
|
|
stage: empty,
|
|
|
|
sprite: empty,
|
|
|
|
simplebutton: empty,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-23 02:27:03 +00:00
|
|
|
/// Add a free-function builtin to the global scope.
|
|
|
|
fn function<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
2020-07-14 02:21:18 +00:00
|
|
|
package: impl Into<AvmString<'gc>>,
|
|
|
|
name: impl Into<AvmString<'gc>>,
|
2021-05-05 12:26:20 +00:00
|
|
|
nf: NativeMethod,
|
2020-02-23 02:27:03 +00:00
|
|
|
fn_proto: Object<'gc>,
|
2020-10-09 01:54:51 +00:00
|
|
|
mut domain: Domain<'gc>,
|
|
|
|
script: Script<'gc>,
|
2020-09-24 03:35:11 +00:00
|
|
|
) -> Result<(), Error> {
|
|
|
|
let name = QName::new(Namespace::package(package), name);
|
|
|
|
let as3fn = FunctionObject::from_builtin(mc, nf, fn_proto).into();
|
2020-10-09 01:54:51 +00:00
|
|
|
domain.export_definition(name.clone(), script, mc)?;
|
2020-09-24 03:35:11 +00:00
|
|
|
script
|
2020-10-09 01:54:51 +00:00
|
|
|
.init()
|
|
|
|
.1
|
2020-09-24 03:35:11 +00:00
|
|
|
.install_dynamic_property(mc, name, as3fn)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
Ok(())
|
2020-02-23 02:27:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-05 03:00:17 +00:00
|
|
|
/// Add a class builtin with prototype methods to the global scope.
|
|
|
|
///
|
|
|
|
/// Since the function has to return a normal prototype object in this case, we
|
|
|
|
/// have to construct a constructor to go along with it, as if we had called
|
|
|
|
/// `install_foreign_trait` with such a class.
|
|
|
|
fn dynamic_class<'gc>(
|
2020-02-23 00:39:12 +00:00
|
|
|
mc: MutationContext<'gc, '_>,
|
2020-08-05 03:00:17 +00:00
|
|
|
constr: Object<'gc>,
|
2020-10-09 01:54:51 +00:00
|
|
|
mut domain: Domain<'gc>,
|
|
|
|
script: Script<'gc>,
|
2020-09-24 03:35:11 +00:00
|
|
|
) -> Result<(), Error> {
|
2021-05-22 02:46:17 +00:00
|
|
|
let class = constr
|
|
|
|
.as_class()
|
|
|
|
.ok_or("Attempted to create builtin dynamic class without class on it's constructor!")?;
|
2020-09-24 03:35:11 +00:00
|
|
|
let name = class.read().name().clone();
|
2020-08-05 03:00:17 +00:00
|
|
|
|
2020-09-24 03:35:11 +00:00
|
|
|
script
|
2020-10-09 01:54:51 +00:00
|
|
|
.init()
|
|
|
|
.1
|
2020-09-24 03:35:11 +00:00
|
|
|
.install_const(mc, name.clone(), 0, constr.into());
|
2020-10-09 01:54:51 +00:00
|
|
|
domain.export_definition(name, script, mc)
|
2020-02-23 00:39:12 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 04:24:16 +00:00
|
|
|
/// Add a class builtin to the global scope.
|
2020-08-05 03:00:17 +00:00
|
|
|
///
|
|
|
|
/// This function returns a prototype which may be stored in `SystemPrototypes`.
|
2020-08-26 03:10:59 +00:00
|
|
|
/// The `custom_derive` is used to select a particular `TObject` impl, or you
|
|
|
|
/// can use `None` to indicate that this class does not change host object
|
|
|
|
/// impls.
|
2021-05-16 02:36:11 +00:00
|
|
|
fn class<'gc>(
|
2020-07-07 04:24:16 +00:00
|
|
|
activation: &mut Activation<'_, 'gc, '_>,
|
|
|
|
class_def: GcCell<'gc, Class<'gc>>,
|
2020-10-09 01:54:51 +00:00
|
|
|
mut domain: Domain<'gc>,
|
|
|
|
script: Script<'gc>,
|
2021-05-28 02:22:38 +00:00
|
|
|
) -> Result<(Object<'gc>, Object<'gc>), Error> {
|
2020-10-09 01:54:51 +00:00
|
|
|
let mut global = script.init().1;
|
2020-07-11 21:39:45 +00:00
|
|
|
let global_scope = Scope::push_scope(global.get_scope(), global, activation.context.gc_context);
|
2020-08-26 03:10:59 +00:00
|
|
|
|
|
|
|
let class_read = class_def.read();
|
|
|
|
let super_class = if let Some(sc_name) = class_read.super_class_name() {
|
|
|
|
let super_name = global
|
|
|
|
.resolve_multiname(sc_name)?
|
|
|
|
.unwrap_or_else(|| QName::dynamic_name("Object"));
|
|
|
|
|
|
|
|
let super_class: Result<Object<'gc>, Error> = global
|
|
|
|
.get_property(global, &super_name, activation)?
|
|
|
|
.coerce_to_object(activation)
|
|
|
|
.map_err(|_e| {
|
|
|
|
format!("Could not resolve superclass {:?}", super_name.local_name()).into()
|
|
|
|
});
|
|
|
|
|
|
|
|
Some(super_class?)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2021-05-31 20:34:46 +00:00
|
|
|
let class_name = class_read.name().clone();
|
|
|
|
drop(class_read);
|
|
|
|
|
|
|
|
let mut constr =
|
2021-05-16 02:36:11 +00:00
|
|
|
ClassObject::from_class(activation, class_def, super_class, Some(global_scope))?;
|
2020-08-26 03:10:59 +00:00
|
|
|
global.install_const(
|
|
|
|
activation.context.gc_context,
|
2021-05-31 20:34:46 +00:00
|
|
|
class_name.clone(),
|
2020-08-26 03:10:59 +00:00
|
|
|
0,
|
|
|
|
constr.into(),
|
|
|
|
);
|
2021-05-31 20:34:46 +00:00
|
|
|
domain.export_definition(class_name, script, activation.context.gc_context)?;
|
2020-07-07 04:24:16 +00:00
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
let proto = constr
|
2020-08-05 03:00:17 +00:00
|
|
|
.get_property(
|
|
|
|
constr,
|
2021-01-24 07:51:36 +00:00
|
|
|
&QName::new(Namespace::public(), "prototype"),
|
2020-08-05 03:00:17 +00:00
|
|
|
activation,
|
|
|
|
)?
|
2021-05-28 02:22:38 +00:00
|
|
|
.coerce_to_object(activation)?;
|
|
|
|
|
|
|
|
Ok((constr, proto))
|
2020-07-07 04:24:16 +00:00
|
|
|
}
|
|
|
|
|
2020-03-09 03:09:30 +00:00
|
|
|
/// Add a builtin constant to the global scope.
|
|
|
|
fn constant<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
2020-07-14 02:21:18 +00:00
|
|
|
package: impl Into<AvmString<'gc>>,
|
|
|
|
name: impl Into<AvmString<'gc>>,
|
2020-03-09 03:09:30 +00:00
|
|
|
value: Value<'gc>,
|
2020-10-09 01:54:51 +00:00
|
|
|
mut domain: Domain<'gc>,
|
|
|
|
script: Script<'gc>,
|
2020-09-24 03:35:11 +00:00
|
|
|
) -> Result<(), Error> {
|
|
|
|
let name = QName::new(Namespace::package(package), name);
|
2020-10-09 01:54:51 +00:00
|
|
|
domain.export_definition(name.clone(), script, mc)?;
|
|
|
|
script.init().1.install_const(mc, name, 0, value);
|
2020-09-24 03:35:11 +00:00
|
|
|
|
|
|
|
Ok(())
|
2020-03-09 03:09:30 +00:00
|
|
|
}
|
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
macro_rules! avm2_system_class {
|
|
|
|
($field:ident, $activation:ident, $class:expr, $domain:expr, $script:expr) => {
|
|
|
|
let (constr, proto) = class($activation, $class, $domain, $script)?;
|
|
|
|
|
|
|
|
let sc = $activation.avm2().system_constructors.as_mut().unwrap();
|
|
|
|
sc.$field = constr;
|
|
|
|
|
|
|
|
let sp = $activation.avm2().system_prototypes.as_mut().unwrap();
|
|
|
|
sp.$field = proto;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-24 03:35:11 +00:00
|
|
|
/// Initialize the player global domain.
|
2020-07-07 04:24:16 +00:00
|
|
|
///
|
2020-08-05 03:00:17 +00:00
|
|
|
/// This should be called only once, to construct the global scope of the
|
|
|
|
/// player. It will return a list of prototypes it has created, which should be
|
2020-09-24 03:35:11 +00:00
|
|
|
/// stored on the AVM. All relevant declarations will also be attached to the
|
|
|
|
/// given domain.
|
|
|
|
pub fn load_player_globals<'gc>(
|
|
|
|
activation: &mut Activation<'_, 'gc, '_>,
|
2020-10-09 01:54:51 +00:00
|
|
|
domain: Domain<'gc>,
|
2020-09-24 03:35:11 +00:00
|
|
|
) -> Result<(), Error> {
|
|
|
|
let mc = activation.context.gc_context;
|
2021-05-22 02:46:17 +00:00
|
|
|
let gs = DomainObject::from_early_domain(mc, domain);
|
2020-09-24 03:35:11 +00:00
|
|
|
let script = Script::empty_script(mc, gs);
|
2020-02-19 03:26:08 +00:00
|
|
|
|
2020-02-23 00:39:12 +00:00
|
|
|
// public / root package
|
2021-05-16 02:36:11 +00:00
|
|
|
//
|
|
|
|
// We have to do this particular dance so that we have Object methods whose
|
|
|
|
// functions have call/apply in their prototypes, and that Function is also
|
|
|
|
// a subclass of Object.
|
2021-05-22 02:46:17 +00:00
|
|
|
let object_proto = object::create_proto(activation);
|
|
|
|
let fn_proto = function::create_proto(activation, object_proto);
|
2020-02-23 00:39:12 +00:00
|
|
|
|
2021-05-31 20:34:46 +00:00
|
|
|
let (object_constr, object_cinit) = object::fill_proto(activation, gs, object_proto, fn_proto)?;
|
|
|
|
let (function_constr, function_cinit) =
|
|
|
|
function::fill_proto(activation, gs, fn_proto, object_constr)?;
|
2021-05-16 02:36:11 +00:00
|
|
|
|
2021-05-31 20:34:46 +00:00
|
|
|
let (class_constr, class_proto, class_cinit) =
|
|
|
|
class::create_class(activation, gs, object_constr, object_proto, fn_proto)?;
|
2020-02-19 03:26:08 +00:00
|
|
|
|
2021-05-22 02:46:17 +00:00
|
|
|
dynamic_class(mc, object_constr, domain, script)?;
|
|
|
|
dynamic_class(mc, function_constr, domain, script)?;
|
|
|
|
dynamic_class(mc, class_constr, domain, script)?;
|
2020-08-05 03:00:17 +00:00
|
|
|
|
|
|
|
// At this point, we need at least a partial set of system prototypes in
|
|
|
|
// order to continue initializing the player. The rest of the prototypes
|
|
|
|
// are set to a bare object until we have a chance to initialize them.
|
|
|
|
activation.context.avm2.system_prototypes = Some(SystemPrototypes::new(
|
2020-02-23 00:39:12 +00:00
|
|
|
object_proto,
|
|
|
|
fn_proto,
|
2020-08-05 03:00:17 +00:00
|
|
|
class_proto,
|
2020-09-24 03:35:11 +00:00
|
|
|
ScriptObject::bare_object(mc),
|
2020-08-05 03:00:17 +00:00
|
|
|
));
|
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
activation.context.avm2.system_constructors = Some(SystemConstructors::new(
|
|
|
|
object_constr,
|
|
|
|
function_constr,
|
|
|
|
class_constr,
|
|
|
|
ScriptObject::bare_object(mc),
|
|
|
|
));
|
|
|
|
|
2021-05-31 20:34:46 +00:00
|
|
|
// We can now run the class initializers for our core classes.
|
|
|
|
// Everything else initializes as it's installed automatically.
|
|
|
|
object_cinit.call(Some(object_constr), &[], activation, Some(object_constr))?;
|
|
|
|
function_cinit.call(
|
|
|
|
Some(function_constr),
|
|
|
|
&[],
|
|
|
|
activation,
|
|
|
|
Some(function_constr),
|
|
|
|
)?;
|
|
|
|
class_cinit.call(Some(class_constr), &[], activation, Some(class_constr))?;
|
2020-08-05 03:00:17 +00:00
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
global,
|
|
|
|
activation,
|
|
|
|
global_scope::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(string, activation, string::create_class(mc), domain, script);
|
|
|
|
avm2_system_class!(
|
|
|
|
boolean,
|
|
|
|
activation,
|
|
|
|
boolean::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(number, activation, number::create_class(mc), domain, script);
|
|
|
|
avm2_system_class!(int, activation, int::create_class(mc), domain, script);
|
|
|
|
avm2_system_class!(uint, activation, uint::create_class(mc), domain, script);
|
|
|
|
avm2_system_class!(
|
|
|
|
namespace,
|
|
|
|
activation,
|
|
|
|
namespace::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(array, activation, array::create_class(mc), domain, script);
|
2020-08-05 03:00:17 +00:00
|
|
|
|
2020-09-24 03:35:11 +00:00
|
|
|
// At this point we have to hide the fact that we had to create the player
|
|
|
|
// globals scope *before* the `Object` class
|
2021-05-28 02:22:38 +00:00
|
|
|
gs.set_proto(mc, activation.avm2().prototypes().global);
|
2020-08-05 03:00:17 +00:00
|
|
|
|
2020-09-24 03:35:11 +00:00
|
|
|
function(mc, "", "trace", trace, fn_proto, domain, script)?;
|
2020-12-28 05:30:11 +00:00
|
|
|
function(mc, "", "isFinite", is_finite, fn_proto, domain, script)?;
|
2020-12-28 04:40:47 +00:00
|
|
|
function(mc, "", "isNaN", is_nan, fn_proto, domain, script)?;
|
2020-09-24 03:35:11 +00:00
|
|
|
constant(mc, "", "undefined", Value::Undefined, domain, script)?;
|
|
|
|
constant(mc, "", "null", Value::Null, domain, script)?;
|
2021-02-12 12:09:04 +00:00
|
|
|
constant(mc, "", "NaN", f64::NAN.into(), domain, script)?;
|
2020-09-24 03:35:11 +00:00
|
|
|
constant(mc, "", "Infinity", f64::INFINITY.into(), domain, script)?;
|
2020-02-23 00:39:12 +00:00
|
|
|
|
2021-05-16 02:36:11 +00:00
|
|
|
class(activation, math::create_class(mc), domain, script)?;
|
|
|
|
class(activation, regexp::create_class(mc), domain, script)?;
|
2020-11-10 23:43:44 +00:00
|
|
|
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(xml, activation, xml::create_class(mc), domain, script);
|
|
|
|
avm2_system_class!(
|
|
|
|
xml_list,
|
|
|
|
activation,
|
|
|
|
xml_list::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script
|
|
|
|
);
|
2021-01-15 22:35:10 +00:00
|
|
|
|
2020-09-27 00:21:11 +00:00
|
|
|
// package `flash.system`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
application_domain,
|
2020-09-27 00:21:11 +00:00
|
|
|
activation,
|
|
|
|
flash::system::application_domain::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-01-16 23:28:49 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::system::system::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2020-09-27 00:21:11 +00:00
|
|
|
|
2020-07-07 04:24:16 +00:00
|
|
|
// package `flash.events`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
event,
|
2020-12-08 02:37:43 +00:00
|
|
|
activation,
|
|
|
|
flash::events::event::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2020-07-11 22:09:51 +00:00
|
|
|
class(
|
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::events::ieventdispatcher::create_interface(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
2020-07-11 22:09:51 +00:00
|
|
|
)?;
|
2020-02-23 00:39:12 +00:00
|
|
|
class(
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::events::eventdispatcher::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
2020-07-07 04:24:16 +00:00
|
|
|
)?;
|
2021-03-05 23:01:02 +00:00
|
|
|
// package `flash.utils`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
bytearray,
|
2021-03-05 23:01:02 +00:00
|
|
|
activation,
|
|
|
|
flash::utils::bytearray::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
|
|
|
|
//We also have to do this to the global scope, too.
|
2021-05-22 02:46:17 +00:00
|
|
|
gs.as_application_domain()
|
|
|
|
.unwrap()
|
|
|
|
.init_default_domain_memory(activation)?;
|
2021-03-05 23:01:02 +00:00
|
|
|
|
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::utils::endian::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2020-02-23 00:39:12 +00:00
|
|
|
|
2021-06-22 08:26:27 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::utils::compression_algorithm::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
|
|
|
|
2021-03-27 16:59:56 +00:00
|
|
|
function(
|
|
|
|
mc,
|
|
|
|
"flash.utils",
|
|
|
|
"getTimer",
|
|
|
|
flash::utils::get_timer,
|
|
|
|
fn_proto,
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
|
|
|
|
2020-02-23 00:39:12 +00:00
|
|
|
// package `flash.display`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
display_object,
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::displayobject::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
shape,
|
2021-02-09 03:40:22 +00:00
|
|
|
activation,
|
|
|
|
flash::display::shape::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2020-02-23 00:39:12 +00:00
|
|
|
class(
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::interactiveobject::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
2020-07-07 04:24:16 +00:00
|
|
|
)?;
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
simplebutton,
|
2021-04-24 01:15:37 +00:00
|
|
|
activation,
|
|
|
|
flash::display::simplebutton::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2020-02-23 00:39:12 +00:00
|
|
|
class(
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::displayobjectcontainer::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
2020-07-07 04:24:16 +00:00
|
|
|
)?;
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
sprite,
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::sprite::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
movieclip,
|
2020-07-07 04:24:16 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::movieclip::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
framelabel,
|
2020-09-17 01:32:00 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::framelabel::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
scene,
|
2020-09-18 01:56:48 +00:00
|
|
|
activation,
|
2020-09-24 03:35:11 +00:00
|
|
|
flash::display::scene::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
graphics,
|
2021-02-11 00:25:27 +00:00
|
|
|
activation,
|
|
|
|
flash::display::graphics::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-02-11 22:28:07 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::jointstyle::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-02-11 22:34:32 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::linescalemode::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-02-11 22:37:18 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::capsstyle::create_class(mc),
|
2021-03-24 23:42:37 +00:00
|
|
|
domain,
|
|
|
|
script,
|
2021-03-20 02:01:44 +00:00
|
|
|
)?;
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
loaderinfo,
|
2021-03-20 02:01:44 +00:00
|
|
|
activation,
|
|
|
|
flash::display::loaderinfo::create_class(mc),
|
2021-02-11 22:37:18 +00:00
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-03-20 03:12:14 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::actionscriptversion::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-03-22 22:48:35 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::swfversion::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
stage,
|
2021-04-17 20:03:19 +00:00
|
|
|
activation,
|
|
|
|
flash::display::stage::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-04-25 22:19:02 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::stagescalemode::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-04-18 03:46:00 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::stagealign::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-04-20 01:47:02 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::stagedisplaystate::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-04-21 22:21:22 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::display::stagequality::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2020-02-12 19:58:33 +00:00
|
|
|
|
2021-03-18 19:03:04 +00:00
|
|
|
// package `flash.geom`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
point,
|
2021-03-18 19:03:04 +00:00
|
|
|
activation,
|
|
|
|
flash::geom::point::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-03-18 19:03:04 +00:00
|
|
|
|
2021-01-05 03:14:14 +00:00
|
|
|
// package `flash.media`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
video,
|
2021-01-05 03:14:14 +00:00
|
|
|
activation,
|
|
|
|
flash::media::video::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-01-05 03:14:14 +00:00
|
|
|
|
2021-02-13 01:32:13 +00:00
|
|
|
// package `flash.text`
|
2021-05-28 02:22:38 +00:00
|
|
|
avm2_system_class!(
|
|
|
|
textfield,
|
2021-02-13 01:32:13 +00:00
|
|
|
activation,
|
|
|
|
flash::text::textfield::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
|
|
|
avm2_system_class!(
|
|
|
|
textformat,
|
2021-02-18 02:40:01 +00:00
|
|
|
activation,
|
|
|
|
flash::text::textformat::create_class(mc),
|
|
|
|
domain,
|
2021-05-28 02:22:38 +00:00
|
|
|
script
|
|
|
|
);
|
2021-02-19 03:00:49 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::text::textfieldautosize::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-02-25 23:07:48 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::text::textformatalign::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-02-27 00:07:07 +00:00
|
|
|
class(
|
|
|
|
activation,
|
|
|
|
flash::text::textfieldtype::create_class(mc),
|
|
|
|
domain,
|
|
|
|
script,
|
|
|
|
)?;
|
2021-02-13 01:32:13 +00:00
|
|
|
|
2020-07-07 04:24:16 +00:00
|
|
|
Ok(())
|
2020-02-12 19:58:33 +00:00
|
|
|
}
|