2020-06-20 12:57:53 +00:00
|
|
|
use crate::avm1::error::Error;
|
2019-09-20 19:11:33 +00:00
|
|
|
use crate::avm1::fscommand;
|
2019-11-30 18:31:11 +00:00
|
|
|
use crate::avm1::function::{Executable, FunctionObject};
|
2019-12-18 16:45:20 +00:00
|
|
|
use crate::avm1::listeners::SystemListeners;
|
2019-10-21 22:37:04 +00:00
|
|
|
use crate::avm1::return_value::ReturnValue;
|
2020-06-28 10:07:27 +00:00
|
|
|
use crate::avm1::stack_frame::StackFrame;
|
|
|
|
use crate::avm1::{Object, ScriptObject, TObject, UpdateContext, Value};
|
2019-09-14 02:53:42 +00:00
|
|
|
use crate::backend::navigator::NavigationMethod;
|
2019-10-08 12:21:07 +00:00
|
|
|
use enumset::EnumSet;
|
2019-12-06 18:24:36 +00:00
|
|
|
use gc_arena::MutationContext;
|
2019-09-02 03:03:50 +00:00
|
|
|
use rand::Rng;
|
2019-11-22 22:32:57 +00:00
|
|
|
use std::f64;
|
2019-09-02 18:45:19 +00:00
|
|
|
|
2019-12-11 23:30:04 +00:00
|
|
|
mod array;
|
2020-01-20 08:32:32 +00:00
|
|
|
pub(crate) mod boolean;
|
2020-03-26 05:25:07 +00:00
|
|
|
pub(crate) mod button;
|
2020-01-04 03:48:16 +00:00
|
|
|
mod color;
|
2020-03-26 05:25:07 +00:00
|
|
|
pub(crate) mod display_object;
|
2019-10-17 02:31:41 +00:00
|
|
|
mod function;
|
2019-12-18 21:25:54 +00:00
|
|
|
mod key;
|
2019-09-02 18:45:19 +00:00
|
|
|
mod math;
|
2020-05-19 19:01:54 +00:00
|
|
|
mod matrix;
|
2019-12-16 21:58:31 +00:00
|
|
|
pub(crate) mod mouse;
|
2019-12-17 09:00:29 +00:00
|
|
|
pub(crate) mod movie_clip;
|
2020-01-15 00:58:32 +00:00
|
|
|
mod movie_clip_loader;
|
2020-01-20 08:19:55 +00:00
|
|
|
pub(crate) mod number;
|
2019-10-17 02:31:41 +00:00
|
|
|
mod object;
|
2020-05-20 12:19:48 +00:00
|
|
|
mod point;
|
2020-05-31 11:58:16 +00:00
|
|
|
mod rectangle;
|
2020-06-15 16:52:49 +00:00
|
|
|
pub(crate) mod shared_object;
|
2019-12-22 23:32:32 +00:00
|
|
|
mod sound;
|
2019-12-18 06:26:09 +00:00
|
|
|
mod stage;
|
2020-01-19 22:10:04 +00:00
|
|
|
pub(crate) mod string;
|
2020-05-26 17:59:20 +00:00
|
|
|
pub(crate) mod system;
|
2020-05-31 02:49:07 +00:00
|
|
|
pub(crate) mod system_capabilities;
|
2020-05-27 21:57:56 +00:00
|
|
|
pub(crate) mod system_ime;
|
2020-05-29 03:29:15 +00:00
|
|
|
pub(crate) mod system_security;
|
2020-05-31 02:49:07 +00:00
|
|
|
pub(crate) mod text_field;
|
2020-01-18 20:04:47 +00:00
|
|
|
mod text_format;
|
2019-12-20 20:28:49 +00:00
|
|
|
mod xml;
|
2019-09-02 18:45:19 +00:00
|
|
|
|
2019-09-20 19:11:33 +00:00
|
|
|
#[allow(non_snake_case, unused_must_use)] //can't use errors yet
|
2019-09-01 22:40:32 +00:00
|
|
|
pub fn getURL<'a, 'gc>(
|
2020-06-28 10:07:27 +00:00
|
|
|
activation: &mut StackFrame<'_, 'gc>,
|
2019-10-27 18:58:30 +00:00
|
|
|
context: &mut UpdateContext<'a, 'gc, '_>,
|
2019-12-06 18:24:36 +00:00
|
|
|
_this: Object<'gc>,
|
2019-09-01 22:40:32 +00:00
|
|
|
args: &[Value<'gc>],
|
2020-06-20 23:02:45 +00:00
|
|
|
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
2019-09-14 03:03:24 +00:00
|
|
|
//TODO: Error behavior if no arguments are present
|
|
|
|
if let Some(url_val) = args.get(0) {
|
2020-06-28 10:07:27 +00:00
|
|
|
let url = url_val.coerce_to_string(activation, context)?;
|
2019-09-20 19:11:33 +00:00
|
|
|
if let Some(fscommand) = fscommand::parse(&url) {
|
2020-06-28 10:07:27 +00:00
|
|
|
fscommand::handle(fscommand, activation, context);
|
2019-10-31 00:25:52 +00:00
|
|
|
return Ok(Value::Undefined.into());
|
2019-09-20 19:11:33 +00:00
|
|
|
}
|
2019-09-26 18:45:45 +00:00
|
|
|
|
2020-06-19 17:08:24 +00:00
|
|
|
let window = if let Some(window) = args.get(1) {
|
2020-06-28 10:07:27 +00:00
|
|
|
Some(window.coerce_to_string(activation, context)?.to_string())
|
2020-06-19 17:08:24 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2019-09-14 03:03:24 +00:00
|
|
|
let method = match args.get(2) {
|
|
|
|
Some(Value::String(s)) if s == "GET" => Some(NavigationMethod::GET),
|
|
|
|
Some(Value::String(s)) if s == "POST" => Some(NavigationMethod::POST),
|
2019-09-17 03:37:11 +00:00
|
|
|
_ => None,
|
2019-09-14 03:03:24 +00:00
|
|
|
};
|
2020-06-28 10:07:27 +00:00
|
|
|
let vars_method = method.map(|m| (m, activation.locals_into_form_values(context)));
|
2019-09-17 03:37:11 +00:00
|
|
|
|
2020-06-19 17:08:24 +00:00
|
|
|
context
|
|
|
|
.navigator
|
|
|
|
.navigate_to_url(url.to_string(), window, vars_method);
|
2019-09-01 22:40:32 +00:00
|
|
|
}
|
|
|
|
|
2019-10-31 00:25:52 +00:00
|
|
|
Ok(Value::Undefined.into())
|
2019-09-01 22:40:32 +00:00
|
|
|
}
|
|
|
|
|
2019-09-02 00:23:55 +00:00
|
|
|
pub fn random<'gc>(
|
2020-06-28 10:07:27 +00:00
|
|
|
_activation: &mut StackFrame<'_, 'gc>,
|
2019-10-27 18:58:30 +00:00
|
|
|
action_context: &mut UpdateContext<'_, 'gc, '_>,
|
2019-12-06 18:24:36 +00:00
|
|
|
_this: Object<'gc>,
|
2019-09-02 00:23:55 +00:00
|
|
|
args: &[Value<'gc>],
|
2020-06-20 23:02:45 +00:00
|
|
|
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
2019-09-02 03:03:50 +00:00
|
|
|
match args.get(0) {
|
2019-11-05 02:47:21 +00:00
|
|
|
Some(Value::Number(max)) => Ok(action_context.rng.gen_range(0.0f64, max).floor().into()),
|
2019-10-31 00:25:52 +00:00
|
|
|
_ => Ok(Value::Undefined.into()), //TODO: Shouldn't this be an error condition?
|
2019-09-02 03:03:50 +00:00
|
|
|
}
|
2019-09-02 00:23:55 +00:00
|
|
|
}
|
|
|
|
|
2019-10-11 14:11:02 +00:00
|
|
|
pub fn is_nan<'gc>(
|
2020-06-28 10:07:27 +00:00
|
|
|
activation: &mut StackFrame<'_, 'gc>,
|
2019-10-27 00:35:22 +00:00
|
|
|
action_context: &mut UpdateContext<'_, 'gc, '_>,
|
2019-12-06 18:24:36 +00:00
|
|
|
_this: Object<'gc>,
|
2019-10-11 14:11:02 +00:00
|
|
|
args: &[Value<'gc>],
|
2020-06-20 23:02:45 +00:00
|
|
|
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
2019-10-11 14:11:02 +00:00
|
|
|
if let Some(val) = args.get(0) {
|
2020-06-28 10:07:27 +00:00
|
|
|
Ok(val
|
|
|
|
.coerce_to_f64(activation, action_context)?
|
|
|
|
.is_nan()
|
|
|
|
.into())
|
2019-10-11 14:11:02 +00:00
|
|
|
} else {
|
2019-11-05 02:47:21 +00:00
|
|
|
Ok(true.into())
|
2019-10-11 14:11:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 22:32:57 +00:00
|
|
|
pub fn get_infinity<'gc>(
|
2020-06-28 10:07:27 +00:00
|
|
|
activation: &mut StackFrame<'_, 'gc>,
|
2019-11-22 22:32:57 +00:00
|
|
|
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
2019-12-06 18:24:36 +00:00
|
|
|
_this: Object<'gc>,
|
2019-11-22 22:32:57 +00:00
|
|
|
_args: &[Value<'gc>],
|
2020-06-20 23:02:45 +00:00
|
|
|
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
2020-06-28 13:42:42 +00:00
|
|
|
if activation.current_swf_version() > 4 {
|
2019-11-22 22:32:57 +00:00
|
|
|
Ok(f64::INFINITY.into())
|
|
|
|
} else {
|
|
|
|
Ok(Value::Undefined.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_nan<'gc>(
|
2020-06-28 10:07:27 +00:00
|
|
|
activation: &mut StackFrame<'_, 'gc>,
|
2019-11-22 22:32:57 +00:00
|
|
|
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
2019-12-06 18:24:36 +00:00
|
|
|
_this: Object<'gc>,
|
2019-11-22 22:32:57 +00:00
|
|
|
_args: &[Value<'gc>],
|
2020-06-20 23:02:45 +00:00
|
|
|
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
2020-06-28 13:42:42 +00:00
|
|
|
if activation.current_swf_version() > 4 {
|
2019-11-22 22:32:57 +00:00
|
|
|
Ok(f64::NAN.into())
|
|
|
|
} else {
|
|
|
|
Ok(Value::Undefined.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-17 02:31:41 +00:00
|
|
|
/// This structure represents all system builtins that are used regardless of
|
|
|
|
/// whatever the hell happens to `_global`. These are, of course,
|
|
|
|
/// user-modifiable.
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct SystemPrototypes<'gc> {
|
2020-03-26 05:25:07 +00:00
|
|
|
pub button: Object<'gc>,
|
2019-12-06 18:24:36 +00:00
|
|
|
pub object: Object<'gc>,
|
|
|
|
pub function: Object<'gc>,
|
|
|
|
pub movie_clip: Object<'gc>,
|
2019-12-22 23:32:32 +00:00
|
|
|
pub sound: Object<'gc>,
|
2019-12-19 09:31:08 +00:00
|
|
|
pub text_field: Object<'gc>,
|
2020-01-19 04:08:27 +00:00
|
|
|
pub text_format: Object<'gc>,
|
2019-12-11 23:30:04 +00:00
|
|
|
pub array: Object<'gc>,
|
2019-12-22 03:50:03 +00:00
|
|
|
pub xml_node: Object<'gc>,
|
2020-01-18 05:54:49 +00:00
|
|
|
pub string: Object<'gc>,
|
2020-01-20 08:19:55 +00:00
|
|
|
pub number: Object<'gc>,
|
2020-01-20 08:32:32 +00:00
|
|
|
pub boolean: Object<'gc>,
|
2020-05-19 19:01:54 +00:00
|
|
|
pub matrix: Object<'gc>,
|
2020-05-20 12:19:48 +00:00
|
|
|
pub point: Object<'gc>,
|
2020-05-31 11:58:16 +00:00
|
|
|
pub rectangle: Object<'gc>,
|
|
|
|
pub rectangle_constructor: Object<'gc>,
|
2020-06-11 23:20:10 +00:00
|
|
|
pub shared_object: Object<'gc>,
|
2019-10-17 02:31:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl<'gc> gc_arena::Collect for SystemPrototypes<'gc> {
|
|
|
|
#[inline]
|
|
|
|
fn trace(&self, cc: gc_arena::CollectionContext) {
|
|
|
|
self.object.trace(cc);
|
|
|
|
self.function.trace(cc);
|
|
|
|
self.movie_clip.trace(cc);
|
2020-03-26 05:25:07 +00:00
|
|
|
self.button.trace(cc);
|
2019-12-22 23:32:32 +00:00
|
|
|
self.sound.trace(cc);
|
2019-12-19 09:31:08 +00:00
|
|
|
self.text_field.trace(cc);
|
2020-01-19 04:08:27 +00:00
|
|
|
self.text_format.trace(cc);
|
2019-12-11 23:30:04 +00:00
|
|
|
self.array.trace(cc);
|
2019-12-22 03:50:03 +00:00
|
|
|
self.xml_node.trace(cc);
|
2020-01-18 05:54:49 +00:00
|
|
|
self.string.trace(cc);
|
2020-01-20 08:19:55 +00:00
|
|
|
self.number.trace(cc);
|
2020-01-20 08:32:32 +00:00
|
|
|
self.boolean.trace(cc);
|
2020-05-19 19:01:54 +00:00
|
|
|
self.matrix.trace(cc);
|
2020-05-20 12:19:48 +00:00
|
|
|
self.point.trace(cc);
|
2020-05-31 11:58:16 +00:00
|
|
|
self.rectangle.trace(cc);
|
|
|
|
self.rectangle_constructor.trace(cc);
|
2020-06-11 23:20:10 +00:00
|
|
|
self.shared_object.trace(cc);
|
2019-10-17 02:31:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize default global scope and builtins for an AVM1 instance.
|
|
|
|
pub fn create_globals<'gc>(
|
|
|
|
gc_context: MutationContext<'gc, '_>,
|
2019-12-18 16:45:20 +00:00
|
|
|
) -> (SystemPrototypes<'gc>, Object<'gc>, SystemListeners<'gc>) {
|
2019-10-25 03:21:35 +00:00
|
|
|
let object_proto = ScriptObject::object_cell(gc_context, None);
|
2019-10-17 02:31:41 +00:00
|
|
|
let function_proto = function::create_proto(gc_context, object_proto);
|
|
|
|
|
|
|
|
object::fill_proto(gc_context, object_proto, function_proto);
|
2019-09-02 18:45:19 +00:00
|
|
|
|
2020-03-26 05:25:07 +00:00
|
|
|
let button_proto: Object<'gc> = button::create_proto(gc_context, object_proto, function_proto);
|
|
|
|
|
2019-12-06 18:24:36 +00:00
|
|
|
let movie_clip_proto: Object<'gc> =
|
2019-10-25 03:21:35 +00:00
|
|
|
movie_clip::create_proto(gc_context, object_proto, function_proto);
|
2019-10-11 14:11:02 +00:00
|
|
|
|
2020-01-15 00:58:32 +00:00
|
|
|
let movie_clip_loader_proto: Object<'gc> =
|
|
|
|
movie_clip_loader::create_proto(gc_context, object_proto, function_proto);
|
|
|
|
|
2019-12-22 23:32:32 +00:00
|
|
|
let sound_proto: Object<'gc> = sound::create_proto(gc_context, object_proto, function_proto);
|
|
|
|
|
2019-12-19 09:31:08 +00:00
|
|
|
let text_field_proto: Object<'gc> =
|
|
|
|
text_field::create_proto(gc_context, object_proto, function_proto);
|
2020-01-18 20:04:47 +00:00
|
|
|
let text_format_proto: Object<'gc> =
|
|
|
|
text_format::create_proto(gc_context, object_proto, function_proto);
|
2019-12-19 09:31:08 +00:00
|
|
|
|
2019-12-11 23:30:04 +00:00
|
|
|
let array_proto: Object<'gc> = array::create_proto(gc_context, object_proto, function_proto);
|
|
|
|
|
2020-01-04 03:48:16 +00:00
|
|
|
let color_proto: Object<'gc> = color::create_proto(gc_context, object_proto, function_proto);
|
2019-12-20 20:28:49 +00:00
|
|
|
let xmlnode_proto: Object<'gc> =
|
|
|
|
xml::create_xmlnode_proto(gc_context, object_proto, function_proto);
|
2020-01-04 03:48:16 +00:00
|
|
|
|
2019-12-20 20:40:50 +00:00
|
|
|
let xml_proto: Object<'gc> = xml::create_xml_proto(gc_context, xmlnode_proto, function_proto);
|
|
|
|
|
2020-01-18 05:54:49 +00:00
|
|
|
let string_proto: Object<'gc> = string::create_proto(gc_context, object_proto, function_proto);
|
2020-01-20 08:19:55 +00:00
|
|
|
let number_proto: Object<'gc> = number::create_proto(gc_context, object_proto, function_proto);
|
2020-01-20 08:32:32 +00:00
|
|
|
let boolean_proto: Object<'gc> =
|
|
|
|
boolean::create_proto(gc_context, object_proto, function_proto);
|
2020-05-19 19:01:54 +00:00
|
|
|
let matrix_proto: Object<'gc> = matrix::create_proto(gc_context, object_proto, function_proto);
|
2020-05-20 12:19:48 +00:00
|
|
|
let point_proto: Object<'gc> = point::create_proto(gc_context, object_proto, function_proto);
|
2020-05-31 11:58:16 +00:00
|
|
|
let rectangle_proto: Object<'gc> =
|
|
|
|
rectangle::create_proto(gc_context, object_proto, function_proto);
|
2020-01-18 05:54:49 +00:00
|
|
|
|
2019-10-23 18:15:46 +00:00
|
|
|
//TODO: These need to be constructors and should also set `.prototype` on each one
|
2020-01-20 21:46:46 +00:00
|
|
|
let object = object::create_object_object(gc_context, object_proto, function_proto);
|
2019-10-23 18:15:46 +00:00
|
|
|
|
2020-03-26 05:25:07 +00:00
|
|
|
let button = FunctionObject::function(
|
|
|
|
gc_context,
|
|
|
|
Executable::Native(button::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(button_proto),
|
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let color = FunctionObject::function(
|
2020-01-04 03:48:16 +00:00
|
|
|
gc_context,
|
|
|
|
Executable::Native(color::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(color_proto),
|
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let function = FunctionObject::function(
|
2019-10-17 02:31:41 +00:00
|
|
|
gc_context,
|
2019-10-23 18:15:46 +00:00
|
|
|
Executable::Native(function::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(function_proto),
|
2019-10-17 02:31:41 +00:00
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let movie_clip = FunctionObject::function(
|
2019-10-17 02:31:41 +00:00
|
|
|
gc_context,
|
2019-10-23 18:15:46 +00:00
|
|
|
Executable::Native(movie_clip::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(movie_clip_proto),
|
2019-10-17 02:31:41 +00:00
|
|
|
);
|
2020-01-15 00:58:32 +00:00
|
|
|
let movie_clip_loader = FunctionObject::function(
|
|
|
|
gc_context,
|
|
|
|
Executable::Native(movie_clip_loader::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(movie_clip_loader_proto),
|
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let sound = FunctionObject::function(
|
2019-12-22 23:32:32 +00:00
|
|
|
gc_context,
|
|
|
|
Executable::Native(sound::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(sound_proto),
|
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let text_field = FunctionObject::function(
|
2019-12-19 09:31:08 +00:00
|
|
|
gc_context,
|
|
|
|
Executable::Native(text_field::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(text_field_proto),
|
|
|
|
);
|
2020-01-18 20:04:47 +00:00
|
|
|
let text_format = FunctionObject::function(
|
|
|
|
gc_context,
|
|
|
|
Executable::Native(text_format::constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(text_format_proto),
|
|
|
|
);
|
2020-03-30 10:20:41 +00:00
|
|
|
let array = array::create_array_object(gc_context, Some(array_proto), Some(function_proto));
|
2019-11-30 18:31:11 +00:00
|
|
|
let xmlnode = FunctionObject::function(
|
2019-12-20 20:28:49 +00:00
|
|
|
gc_context,
|
|
|
|
Executable::Native(xml::xmlnode_constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(xmlnode_proto),
|
|
|
|
);
|
2019-11-30 18:31:11 +00:00
|
|
|
let xml = FunctionObject::function(
|
2019-12-20 20:40:50 +00:00
|
|
|
gc_context,
|
|
|
|
Executable::Native(xml::xml_constructor),
|
|
|
|
Some(function_proto),
|
|
|
|
Some(xml_proto),
|
|
|
|
);
|
2020-01-18 22:48:34 +00:00
|
|
|
let string = string::create_string_object(gc_context, Some(string_proto), Some(function_proto));
|
2020-01-20 08:19:55 +00:00
|
|
|
let number = number::create_number_object(gc_context, Some(number_proto), Some(function_proto));
|
2020-01-20 08:32:32 +00:00
|
|
|
let boolean =
|
|
|
|
boolean::create_boolean_object(gc_context, Some(boolean_proto), Some(function_proto));
|
2019-10-17 02:31:41 +00:00
|
|
|
|
2020-05-19 19:01:54 +00:00
|
|
|
let flash = ScriptObject::object(gc_context, Some(object_proto));
|
|
|
|
let geom = ScriptObject::object(gc_context, Some(object_proto));
|
|
|
|
let matrix = matrix::create_matrix_object(gc_context, Some(matrix_proto), Some(function_proto));
|
2020-05-31 02:14:30 +00:00
|
|
|
|
2020-05-20 12:19:48 +00:00
|
|
|
let point = point::create_point_object(gc_context, Some(point_proto), Some(function_proto));
|
2020-05-31 11:58:16 +00:00
|
|
|
let rectangle =
|
|
|
|
rectangle::create_rectangle_object(gc_context, Some(rectangle_proto), Some(function_proto));
|
2020-05-19 19:01:54 +00:00
|
|
|
|
|
|
|
flash.define_value(gc_context, "geom", geom.into(), EnumSet::empty());
|
|
|
|
geom.define_value(gc_context, "Matrix", matrix.into(), EnumSet::empty());
|
2020-05-20 12:19:48 +00:00
|
|
|
geom.define_value(gc_context, "Point", point.into(), EnumSet::empty());
|
2020-05-31 11:58:16 +00:00
|
|
|
geom.define_value(gc_context, "Rectangle", rectangle.into(), EnumSet::empty());
|
2020-05-19 19:01:54 +00:00
|
|
|
|
2019-12-18 16:45:20 +00:00
|
|
|
let listeners = SystemListeners::new(gc_context, Some(array_proto));
|
|
|
|
|
2019-12-06 18:24:36 +00:00
|
|
|
let mut globals = ScriptObject::bare_object(gc_context);
|
2020-05-19 19:01:54 +00:00
|
|
|
globals.define_value(gc_context, "flash", flash.into(), EnumSet::empty());
|
2019-12-11 23:30:04 +00:00
|
|
|
globals.define_value(gc_context, "Array", array.into(), EnumSet::empty());
|
2020-03-26 05:25:07 +00:00
|
|
|
globals.define_value(gc_context, "Button", button.into(), EnumSet::empty());
|
2020-01-04 03:48:16 +00:00
|
|
|
globals.define_value(gc_context, "Color", color.into(), EnumSet::empty());
|
2019-12-06 18:24:36 +00:00
|
|
|
globals.define_value(gc_context, "Object", object.into(), EnumSet::empty());
|
|
|
|
globals.define_value(gc_context, "Function", function.into(), EnumSet::empty());
|
|
|
|
globals.define_value(gc_context, "MovieClip", movie_clip.into(), EnumSet::empty());
|
2020-01-15 00:58:32 +00:00
|
|
|
globals.define_value(
|
|
|
|
gc_context,
|
|
|
|
"MovieClipLoader",
|
|
|
|
movie_clip_loader.into(),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-12-22 23:32:32 +00:00
|
|
|
globals.define_value(gc_context, "Sound", sound.into(), EnumSet::empty());
|
2019-12-19 09:31:08 +00:00
|
|
|
globals.define_value(gc_context, "TextField", text_field.into(), EnumSet::empty());
|
2020-01-18 20:04:47 +00:00
|
|
|
globals.define_value(
|
|
|
|
gc_context,
|
|
|
|
"TextFormat",
|
|
|
|
text_format.into(),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-12-20 20:28:49 +00:00
|
|
|
globals.define_value(gc_context, "XMLNode", xmlnode.into(), EnumSet::empty());
|
2019-12-20 20:40:50 +00:00
|
|
|
globals.define_value(gc_context, "XML", xml.into(), EnumSet::empty());
|
2020-01-18 05:54:49 +00:00
|
|
|
globals.define_value(gc_context, "String", string.into(), EnumSet::empty());
|
2020-01-20 08:19:55 +00:00
|
|
|
globals.define_value(gc_context, "Number", number.into(), EnumSet::empty());
|
2020-01-20 08:32:32 +00:00
|
|
|
globals.define_value(gc_context, "Boolean", boolean.into(), EnumSet::empty());
|
2020-05-31 02:14:30 +00:00
|
|
|
|
2020-06-11 23:20:10 +00:00
|
|
|
let shared_object_proto = shared_object::create_proto(gc_context, object_proto, function_proto);
|
|
|
|
|
2020-06-15 16:52:49 +00:00
|
|
|
let shared_obj = shared_object::create_shared_object_object(
|
|
|
|
gc_context,
|
|
|
|
Some(shared_object_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
);
|
|
|
|
globals.define_value(
|
|
|
|
gc_context,
|
|
|
|
"SharedObject",
|
|
|
|
shared_obj.into(),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2020-06-11 23:20:10 +00:00
|
|
|
|
2020-05-31 02:49:07 +00:00
|
|
|
let system_security =
|
|
|
|
system_security::create(gc_context, Some(object_proto), Some(function_proto));
|
2020-05-31 02:14:30 +00:00
|
|
|
let system_capabilities = system_capabilities::create(gc_context, Some(object_proto));
|
2020-05-31 02:49:07 +00:00
|
|
|
let system_ime = system_ime::create(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
&listeners.ime,
|
|
|
|
);
|
2020-05-31 02:14:30 +00:00
|
|
|
|
2020-05-31 02:49:07 +00:00
|
|
|
let system = system::create(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
system_security,
|
|
|
|
system_capabilities,
|
|
|
|
system_ime,
|
|
|
|
);
|
2020-05-26 17:59:20 +00:00
|
|
|
globals.define_value(gc_context, "System", system.into(), EnumSet::empty());
|
2020-01-20 08:32:32 +00:00
|
|
|
|
2019-10-25 23:30:05 +00:00
|
|
|
globals.define_value(
|
2019-12-06 18:24:36 +00:00
|
|
|
gc_context,
|
2019-10-17 02:31:41 +00:00
|
|
|
"Math",
|
|
|
|
Value::Object(math::create(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
)),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-12-16 21:58:31 +00:00
|
|
|
globals.define_value(
|
|
|
|
gc_context,
|
|
|
|
"Mouse",
|
|
|
|
Value::Object(mouse::create_mouse_object(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(function_proto),
|
2019-12-18 16:45:20 +00:00
|
|
|
&listeners.mouse,
|
2019-12-16 21:58:31 +00:00
|
|
|
)),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-12-18 21:25:54 +00:00
|
|
|
globals.define_value(
|
|
|
|
gc_context,
|
|
|
|
"Key",
|
|
|
|
Value::Object(key::create_key_object(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
)),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
|
|
|
globals.define_value(
|
2019-12-18 06:26:09 +00:00
|
|
|
gc_context,
|
|
|
|
"Stage",
|
|
|
|
Value::Object(stage::create_stage_object(
|
|
|
|
gc_context,
|
|
|
|
Some(object_proto),
|
|
|
|
Some(array_proto),
|
|
|
|
Some(function_proto),
|
|
|
|
)),
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-10-17 02:31:41 +00:00
|
|
|
globals.force_set_function(
|
|
|
|
"isNaN",
|
|
|
|
is_nan,
|
|
|
|
gc_context,
|
|
|
|
EnumSet::empty(),
|
|
|
|
Some(function_proto),
|
|
|
|
);
|
|
|
|
globals.force_set_function(
|
|
|
|
"getURL",
|
|
|
|
getURL,
|
|
|
|
gc_context,
|
|
|
|
EnumSet::empty(),
|
|
|
|
Some(function_proto),
|
|
|
|
);
|
|
|
|
globals.force_set_function(
|
|
|
|
"random",
|
|
|
|
random,
|
|
|
|
gc_context,
|
|
|
|
EnumSet::empty(),
|
|
|
|
Some(function_proto),
|
|
|
|
);
|
2019-11-03 21:52:10 +00:00
|
|
|
globals.force_set_function(
|
|
|
|
"ASSetPropFlags",
|
|
|
|
object::as_set_prop_flags,
|
|
|
|
gc_context,
|
|
|
|
EnumSet::empty(),
|
|
|
|
Some(function_proto),
|
|
|
|
);
|
2019-11-22 22:32:57 +00:00
|
|
|
globals.add_property(
|
2019-12-06 18:24:36 +00:00
|
|
|
gc_context,
|
|
|
|
"NaN",
|
|
|
|
Executable::Native(get_nan),
|
|
|
|
None,
|
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
|
|
|
globals.add_property(
|
|
|
|
gc_context,
|
2019-10-08 12:21:07 +00:00
|
|
|
"Infinity",
|
2019-11-22 22:32:57 +00:00
|
|
|
Executable::Native(get_infinity),
|
|
|
|
None,
|
2019-10-08 12:21:07 +00:00
|
|
|
EnumSet::empty(),
|
|
|
|
);
|
2019-09-02 18:45:19 +00:00
|
|
|
|
2019-10-17 02:31:41 +00:00
|
|
|
(
|
|
|
|
SystemPrototypes {
|
2020-03-26 05:25:07 +00:00
|
|
|
button: button_proto,
|
2019-10-17 02:31:41 +00:00
|
|
|
object: object_proto,
|
|
|
|
function: function_proto,
|
|
|
|
movie_clip: movie_clip_proto,
|
2019-12-22 23:32:32 +00:00
|
|
|
sound: sound_proto,
|
2019-12-19 09:31:08 +00:00
|
|
|
text_field: text_field_proto,
|
2020-01-19 04:08:27 +00:00
|
|
|
text_format: text_format_proto,
|
2019-12-11 23:30:04 +00:00
|
|
|
array: array_proto,
|
2019-12-22 03:50:03 +00:00
|
|
|
xml_node: xmlnode_proto,
|
2020-01-18 05:54:49 +00:00
|
|
|
string: string_proto,
|
2020-01-20 08:19:55 +00:00
|
|
|
number: number_proto,
|
2020-01-20 08:32:32 +00:00
|
|
|
boolean: boolean_proto,
|
2020-05-19 19:01:54 +00:00
|
|
|
matrix: matrix_proto,
|
2020-05-20 12:19:48 +00:00
|
|
|
point: point_proto,
|
2020-05-31 11:58:16 +00:00
|
|
|
rectangle: rectangle_proto,
|
|
|
|
rectangle_constructor: rectangle,
|
2020-06-11 23:20:10 +00:00
|
|
|
shared_object: shared_object_proto,
|
2019-10-17 02:31:41 +00:00
|
|
|
},
|
2019-12-06 18:24:36 +00:00
|
|
|
globals.into(),
|
2019-12-18 16:45:20 +00:00
|
|
|
listeners,
|
2019-10-17 02:31:41 +00:00
|
|
|
)
|
2019-09-17 03:37:11 +00:00
|
|
|
}
|
2019-10-10 12:28:14 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
2019-10-14 15:30:17 +00:00
|
|
|
#[allow(clippy::unreadable_literal)]
|
2019-10-10 12:28:14 +00:00
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2020-06-28 10:07:27 +00:00
|
|
|
fn setup<'gc>(
|
|
|
|
_activation: &mut StackFrame<'_, 'gc>,
|
|
|
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
|
|
|
) -> Object<'gc> {
|
2019-11-26 19:30:48 +00:00
|
|
|
create_globals(context.gc_context).1
|
2019-10-10 12:28:14 +00:00
|
|
|
}
|
|
|
|
|
2019-11-26 19:30:48 +00:00
|
|
|
test_method!(boolean_function, "Boolean", setup,
|
2019-11-24 22:56:35 +00:00
|
|
|
[19] => {
|
|
|
|
[true] => true,
|
|
|
|
[false] => false,
|
|
|
|
[10.0] => true,
|
|
|
|
[-10.0] => true,
|
|
|
|
[0.0] => false,
|
|
|
|
[std::f64::INFINITY] => true,
|
|
|
|
[std::f64::NAN] => false,
|
|
|
|
[""] => false,
|
|
|
|
["Hello"] => true,
|
|
|
|
[" "] => true,
|
|
|
|
["0"] => true,
|
|
|
|
["1"] => true,
|
2020-01-20 22:06:15 +00:00
|
|
|
[Value::Undefined] => false,
|
|
|
|
[Value::Null] => false,
|
|
|
|
[] => Value::Undefined
|
2019-11-24 22:56:35 +00:00
|
|
|
},
|
|
|
|
[6] => {
|
|
|
|
[true] => true,
|
|
|
|
[false] => false,
|
|
|
|
[10.0] => true,
|
|
|
|
[-10.0] => true,
|
|
|
|
[0.0] => false,
|
|
|
|
[std::f64::INFINITY] => true,
|
|
|
|
[std::f64::NAN] => false,
|
|
|
|
[""] => false,
|
|
|
|
["Hello"] => false,
|
|
|
|
[" "] => false,
|
|
|
|
["0"] => false,
|
|
|
|
["1"] => true,
|
2020-01-20 22:06:15 +00:00
|
|
|
[Value::Undefined] => false,
|
|
|
|
[Value::Null] => false,
|
|
|
|
[] => Value::Undefined
|
2019-11-24 22:56:35 +00:00
|
|
|
}
|
2019-10-10 12:28:14 +00:00
|
|
|
);
|
|
|
|
|
2019-11-26 19:30:48 +00:00
|
|
|
test_method!(is_nan_function, "isNaN", setup,
|
2019-11-24 22:56:35 +00:00
|
|
|
[19] => {
|
|
|
|
[true] => false,
|
|
|
|
[false] => false,
|
|
|
|
[10.0] => false,
|
|
|
|
[-10.0] => false,
|
|
|
|
[0.0] => false,
|
|
|
|
[std::f64::INFINITY] => false,
|
|
|
|
[std::f64::NAN] => true,
|
2019-11-24 21:13:48 +00:00
|
|
|
[""] => true,
|
2019-11-24 22:56:35 +00:00
|
|
|
["Hello"] => true,
|
|
|
|
[" "] => true,
|
|
|
|
[" 5 "] => true,
|
|
|
|
["0"] => false,
|
|
|
|
["1"] => false,
|
|
|
|
["Infinity"] => true,
|
|
|
|
["100a"] => true,
|
|
|
|
["0x10"] => false,
|
|
|
|
["0xhello"] => true,
|
|
|
|
["0x1999999981ffffff"] => false,
|
|
|
|
["0xUIXUIDFKHJDF012345678"] => true,
|
|
|
|
["123e-1"] => false,
|
|
|
|
[] => true
|
|
|
|
}
|
2019-10-11 14:11:02 +00:00
|
|
|
);
|
|
|
|
|
2019-11-26 19:30:48 +00:00
|
|
|
test_method!(number_function, "Number", setup,
|
2019-11-24 21:13:48 +00:00
|
|
|
[5, 6] => {
|
2019-11-24 22:56:35 +00:00
|
|
|
[true] => 1.0,
|
|
|
|
[false] => 0.0,
|
|
|
|
[10.0] => 10.0,
|
|
|
|
[-10.0] => -10.0,
|
2019-11-24 21:13:48 +00:00
|
|
|
["true"] => std::f64::NAN,
|
|
|
|
["false"] => std::f64::NAN,
|
|
|
|
[1.0] => 1.0,
|
2019-11-24 22:56:35 +00:00
|
|
|
[0.0] => 0.0,
|
2019-11-24 21:13:48 +00:00
|
|
|
[0.000] => 0.0,
|
|
|
|
["0.000"] => 0.0,
|
|
|
|
["True"] => std::f64::NAN,
|
|
|
|
["False"] => std::f64::NAN,
|
2019-11-24 22:56:35 +00:00
|
|
|
[std::f64::NAN] => std::f64::NAN,
|
2019-11-24 21:13:48 +00:00
|
|
|
[std::f64::INFINITY] => std::f64::INFINITY,
|
|
|
|
[std::f64::NEG_INFINITY] => std::f64::NEG_INFINITY,
|
|
|
|
[" 12"] => 12.0,
|
2020-02-25 23:56:30 +00:00
|
|
|
[" \t\r\n12"] => 12.0,
|
|
|
|
["\u{A0}12"] => std::f64::NAN,
|
2019-11-24 21:13:48 +00:00
|
|
|
[" 0x12"] => std::f64::NAN,
|
|
|
|
["01.2"] => 1.2,
|
|
|
|
[""] => std::f64::NAN,
|
2019-11-24 22:56:35 +00:00
|
|
|
["Hello"] => std::f64::NAN,
|
|
|
|
[" "] => std::f64::NAN,
|
|
|
|
[" 5 "] => std::f64::NAN,
|
|
|
|
["0"] => 0.0,
|
|
|
|
["1"] => 1.0,
|
|
|
|
["Infinity"] => std::f64::NAN,
|
|
|
|
["100a"] => std::f64::NAN,
|
|
|
|
["0xhello"] => std::f64::NAN,
|
|
|
|
["123e-1"] => 12.3,
|
|
|
|
["0xUIXUIDFKHJDF012345678"] => std::f64::NAN,
|
|
|
|
[] => 0.0
|
2019-11-24 21:13:48 +00:00
|
|
|
},
|
|
|
|
[5] => {
|
|
|
|
["0x12"] => std::f64::NAN,
|
|
|
|
["0x10"] => std::f64::NAN,
|
2020-02-25 23:56:30 +00:00
|
|
|
["0x1999999981ffffff"] => std::f64::NAN,
|
|
|
|
["010"] => 10,
|
|
|
|
["-010"] => -10,
|
|
|
|
["+010"] => 10,
|
|
|
|
[" 010"] => 10,
|
|
|
|
[" -010"] => -10,
|
|
|
|
[" +010"] => 10,
|
|
|
|
["037777777777"] => 37777777777.0,
|
|
|
|
["-037777777777"] => -37777777777.0
|
2019-11-24 21:13:48 +00:00
|
|
|
},
|
|
|
|
[6, 7] => {
|
|
|
|
["0x12"] => 18.0,
|
|
|
|
["0x10"] => 16.0,
|
2020-02-25 23:56:30 +00:00
|
|
|
["-0x10"] => std::f64::NAN,
|
|
|
|
["0x1999999981ffffff"] => -2113929217.0,
|
|
|
|
["010"] => 8,
|
|
|
|
["-010"] => -8,
|
|
|
|
["+010"] => 8,
|
|
|
|
[" 010"] => 10,
|
|
|
|
[" -010"] => -10,
|
|
|
|
[" +010"] => 10,
|
|
|
|
["037777777777"] => -1,
|
|
|
|
["-037777777777"] => 1
|
2019-11-24 21:13:48 +00:00
|
|
|
},
|
|
|
|
[5, 6] => {
|
|
|
|
[Value::Undefined] => 0.0,
|
|
|
|
[Value::Null] => 0.0
|
|
|
|
},
|
|
|
|
[7] => {
|
|
|
|
[Value::Undefined] => std::f64::NAN,
|
|
|
|
[Value::Null] => std::f64::NAN
|
2019-11-24 22:56:35 +00:00
|
|
|
}
|
2019-10-11 14:11:02 +00:00
|
|
|
);
|
2019-10-10 12:28:14 +00:00
|
|
|
}
|