2020-02-12 19:58:33 +00:00
|
|
|
//! Global scope built-ins
|
|
|
|
|
2020-07-03 01:49:53 +00:00
|
|
|
use crate::avm2::function::FunctionObject;
|
|
|
|
use crate::avm2::method::NativeMethod;
|
2020-02-19 03:26:08 +00:00
|
|
|
use crate::avm2::names::{Namespace, QName};
|
2020-02-12 19:58:33 +00:00
|
|
|
use crate::avm2::object::{Object, TObject};
|
2020-02-23 02:27:03 +00:00
|
|
|
use crate::avm2::return_value::ReturnValue;
|
2020-02-12 19:58:33 +00:00
|
|
|
use crate::avm2::script_object::ScriptObject;
|
2020-02-23 02:27:03 +00:00
|
|
|
use crate::avm2::value::Value;
|
|
|
|
use crate::avm2::{Avm2, Error};
|
|
|
|
use crate::context::UpdateContext;
|
2020-02-19 03:26:08 +00:00
|
|
|
use gc_arena::{Collect, MutationContext};
|
2020-03-09 03:09:30 +00:00
|
|
|
use std::f64::NAN;
|
2020-02-12 19:58:33 +00:00
|
|
|
|
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;
|
|
|
|
mod object;
|
|
|
|
|
2020-02-23 02:27:03 +00:00
|
|
|
fn trace<'gc>(
|
|
|
|
_avm: &mut Avm2<'gc>,
|
|
|
|
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
2020-02-24 03:11:02 +00:00
|
|
|
_this: Option<Object<'gc>>,
|
2020-02-23 02:27:03 +00:00
|
|
|
args: &[Value<'gc>],
|
|
|
|
) -> Result<ReturnValue<'gc>, Error> {
|
|
|
|
if let Some(s) = args.get(0) {
|
2020-03-06 20:32:47 +00:00
|
|
|
log::info!(target: "avm_trace", "{}", s.clone().coerce_string());
|
2020-02-23 02:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Value::Undefined.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-02-19 03:26:08 +00:00
|
|
|
}
|
|
|
|
|
2020-02-23 02:27:03 +00:00
|
|
|
/// Add a free-function builtin to the global scope.
|
|
|
|
fn function<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
|
|
|
mut global_scope: Object<'gc>,
|
|
|
|
package: &str,
|
|
|
|
name: &str,
|
2020-07-03 01:49:53 +00:00
|
|
|
nf: NativeMethod<'gc>,
|
2020-02-23 02:27:03 +00:00
|
|
|
fn_proto: Object<'gc>,
|
|
|
|
) {
|
|
|
|
global_scope
|
|
|
|
.install_dynamic_property(
|
|
|
|
mc,
|
|
|
|
QName::new(Namespace::package(package), name),
|
|
|
|
FunctionObject::from_builtin(mc, nf, fn_proto).into(),
|
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a class builtin to the global scope.
|
2020-02-23 00:39:12 +00:00
|
|
|
fn class<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
|
|
|
mut global_scope: Object<'gc>,
|
|
|
|
package: &str,
|
|
|
|
name: &str,
|
2020-07-03 01:49:53 +00:00
|
|
|
constr: NativeMethod<'gc>,
|
2020-02-23 00:39:12 +00:00
|
|
|
proto: Object<'gc>,
|
|
|
|
fn_proto: Object<'gc>,
|
|
|
|
) {
|
|
|
|
global_scope
|
|
|
|
.install_dynamic_property(
|
|
|
|
mc,
|
|
|
|
QName::new(Namespace::package(package), name),
|
|
|
|
FunctionObject::from_builtin_constr(mc, constr, proto, fn_proto)
|
|
|
|
.unwrap()
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2020-03-09 03:09:30 +00:00
|
|
|
/// Add a builtin constant to the global scope.
|
|
|
|
fn constant<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
|
|
|
mut global_scope: Object<'gc>,
|
|
|
|
package: &str,
|
|
|
|
name: &str,
|
|
|
|
value: Value<'gc>,
|
|
|
|
) {
|
|
|
|
global_scope.install_const(mc, QName::new(Namespace::package(package), name), 0, value)
|
|
|
|
}
|
|
|
|
|
2020-02-19 03:26:08 +00:00
|
|
|
/// Construct a new global scope.
|
|
|
|
///
|
|
|
|
/// This function returns both the global scope object, as well as all builtin
|
|
|
|
/// prototypes that other parts of the VM will need to use.
|
|
|
|
pub fn construct_global_scope<'gc>(
|
|
|
|
mc: MutationContext<'gc, '_>,
|
|
|
|
) -> (Object<'gc>, SystemPrototypes<'gc>) {
|
2020-02-23 00:39:12 +00:00
|
|
|
let gs = ScriptObject::bare_object(mc);
|
2020-02-19 03:26:08 +00:00
|
|
|
|
2020-02-23 00:39:12 +00:00
|
|
|
// public / root package
|
2020-02-19 03:26:08 +00:00
|
|
|
let object_proto = ScriptObject::bare_object(mc);
|
2020-02-23 00:39:12 +00:00
|
|
|
let fn_proto = function::create_proto(mc, object_proto);
|
2020-03-09 01:53:33 +00:00
|
|
|
let class_proto = class::create_proto(mc, object_proto, fn_proto);
|
2020-02-23 00:39:12 +00:00
|
|
|
|
|
|
|
object::fill_proto(mc, object_proto, fn_proto);
|
2020-02-19 03:26:08 +00:00
|
|
|
|
2020-02-23 00:39:12 +00:00
|
|
|
class(
|
|
|
|
mc,
|
|
|
|
gs,
|
|
|
|
"",
|
|
|
|
"Object",
|
|
|
|
object::constructor,
|
|
|
|
object_proto,
|
|
|
|
fn_proto,
|
|
|
|
);
|
|
|
|
class(
|
|
|
|
mc,
|
|
|
|
gs,
|
|
|
|
"",
|
|
|
|
"Function",
|
|
|
|
function::constructor,
|
|
|
|
fn_proto,
|
|
|
|
fn_proto,
|
|
|
|
);
|
2020-03-09 01:53:33 +00:00
|
|
|
class(
|
|
|
|
mc,
|
|
|
|
gs,
|
|
|
|
"",
|
|
|
|
"Class",
|
|
|
|
class::constructor,
|
|
|
|
class_proto,
|
|
|
|
fn_proto,
|
|
|
|
);
|
2020-02-23 02:27:03 +00:00
|
|
|
function(mc, gs, "", "trace", trace, fn_proto);
|
2020-03-09 03:09:30 +00:00
|
|
|
constant(mc, gs, "", "undefined", Value::Undefined);
|
|
|
|
constant(mc, gs, "", "null", Value::Null);
|
|
|
|
constant(mc, gs, "", "NaN", NAN.into());
|
2020-02-23 00:39:12 +00:00
|
|
|
|
|
|
|
// 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,
|
|
|
|
);
|
2020-02-19 03:26:08 +00:00
|
|
|
|
|
|
|
let system_prototypes = SystemPrototypes {
|
|
|
|
object: object_proto,
|
2020-02-23 00:39:12 +00:00
|
|
|
function: fn_proto,
|
2020-03-09 01:53:33 +00:00
|
|
|
class: class_proto,
|
2020-02-19 03:26:08 +00:00
|
|
|
};
|
2020-02-12 19:58:33 +00:00
|
|
|
|
2020-02-23 00:39:12 +00:00
|
|
|
(gs, system_prototypes)
|
2020-02-12 19:58:33 +00:00
|
|
|
}
|