Skip to content

Commit

Permalink
avm2: Generate class traits from const arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
adrian17 authored and Herschel committed May 6, 2021
1 parent 8312243 commit 46ddb9b
Show file tree
Hide file tree
Showing 38 changed files with 829 additions and 2,163 deletions.
97 changes: 96 additions & 1 deletion core/src/avm2/class.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! AVM2 classes
use crate::avm2::method::Method;
use crate::avm2::method::{GenericNativeMethod, Method};
use crate::avm2::names::{Multiname, Namespace, QName};
use crate::avm2::script::TranslationUnit;
use crate::avm2::string::AvmString;
Expand Down Expand Up @@ -342,6 +342,100 @@ impl<'gc> Class<'gc> {
&self.super_class
}

#[inline(never)]
pub fn define_public_constant_string_class_traits(
&mut self,
items: &[(&'static str, &'static str)],
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
QName::new(Namespace::public(), "String").into(),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_constant_number_class_traits(&mut self, items: &[(&'static str, f64)]) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
QName::new(Namespace::public(), "Number").into(),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_constant_uint_class_traits(&mut self, items: &[(&'static str, u32)]) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
QName::new(Namespace::public(), "uint").into(),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_builtin_instance_methods(
&mut self,
items: &[(&'static str, GenericNativeMethod)],
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_method(
QName::new(Namespace::public(), name),
Method::from_builtin(value),
));
}
}
#[inline(never)]
pub fn define_as3_builtin_instance_methods(
&mut self,
items: &[(&'static str, GenericNativeMethod)],
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), name),
Method::from_builtin(value),
));
}
}
#[inline(never)]
pub fn define_public_builtin_class_methods(
&mut self,
items: &[(&'static str, GenericNativeMethod)],
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_method(
QName::new(Namespace::public(), name),
Method::from_builtin(value),
));
}
}
#[inline(never)]
pub fn define_public_builtin_instance_properties(
&mut self,
items: &[(
&'static str,
Option<GenericNativeMethod>,
Option<GenericNativeMethod>,
)],
) {
for &(name, getter, setter) in items {
if let Some(getter) = getter {
self.define_instance_trait(Trait::from_getter(
QName::new(Namespace::public(), name),
Method::from_builtin(getter),
));
}
if let Some(setter) = setter {
self.define_instance_trait(Trait::from_setter(
QName::new(Namespace::public(), name),
Method::from_builtin(setter),
));
}
}
}

/// Define a trait on the class.
///
/// Class traits will be accessible as properties on the class constructor
Expand All @@ -350,6 +444,7 @@ impl<'gc> Class<'gc> {
self.class_traits.push(my_trait);
}


/// Given a name, append class traits matching the name to a list of known
/// traits.
///
Expand Down
198 changes: 52 additions & 146 deletions core/src/avm2/globals/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
use crate::avm2::activation::Activation;
use crate::avm2::array::ArrayStorage;
use crate::avm2::class::Class;
use crate::avm2::method::Method;
use crate::avm2::names::{Multiname, Namespace, QName};
use crate::avm2::method::{GenericNativeMethod, Method};
use crate::avm2::names::{Namespace, QName};
use crate::avm2::object::{ArrayObject, Object, TObject};
use crate::avm2::string::AvmString;
use crate::avm2::traits::Trait;
use crate::avm2::value::Value;
use crate::avm2::Error;
use bitflags::bitflags;
Expand Down Expand Up @@ -1230,149 +1229,56 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>

let mut write = class.write(mc);

write.define_instance_trait(Trait::from_getter(
QName::new(Namespace::public(), "length"),
Method::from_builtin(length),
));
write.define_instance_trait(Trait::from_setter(
QName::new(Namespace::public(), "length"),
Method::from_builtin(set_length),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "concat"),
Method::from_builtin(concat),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "join"),
Method::from_builtin(join),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::public(), "toString"),
Method::from_builtin(to_string),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::public(), "toLocaleString"),
Method::from_builtin(to_locale_string),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::public(), "valueOf"),
Method::from_builtin(value_of),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "forEach"),
Method::from_builtin(for_each),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "map"),
Method::from_builtin(map),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "filter"),
Method::from_builtin(filter),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "every"),
Method::from_builtin(every),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "some"),
Method::from_builtin(some),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "indexOf"),
Method::from_builtin(index_of),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "lastIndexOf"),
Method::from_builtin(last_index_of),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "pop"),
Method::from_builtin(pop),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "push"),
Method::from_builtin(push),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "reverse"),
Method::from_builtin(reverse),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "shift"),
Method::from_builtin(shift),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "unshift"),
Method::from_builtin(unshift),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "slice"),
Method::from_builtin(slice),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "splice"),
Method::from_builtin(splice),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "sort"),
Method::from_builtin(sort),
));

write.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), "sortOn"),
Method::from_builtin(sort_on),
));

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "CASEINSENSITIVE"),
Multiname::from(QName::new(Namespace::public(), "uint")),
Some(SortOptions::CASE_INSENSITIVE.bits().into()),
));

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "DESCENDING"),
Multiname::from(QName::new(Namespace::public(), "uint")),
Some(SortOptions::DESCENDING.bits().into()),
));

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "NUMERIC"),
Multiname::from(QName::new(Namespace::public(), "uint")),
Some(SortOptions::NUMERIC.bits().into()),
));

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "RETURNINDEXEDARRAY"),
Multiname::from(QName::new(Namespace::public(), "uint")),
Some(SortOptions::RETURN_INDEXED_ARRAY.bits().into()),
));

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "UNIQUESORT"),
Multiname::from(QName::new(Namespace::public(), "uint")),
Some(SortOptions::UNIQUE_SORT.bits().into()),
));
const PUBLIC_INSTANCE_METHODS: &[(&'static str, GenericNativeMethod)] = &[
("toString", to_string),
("toLocaleString", to_locale_string),
("valueOf", value_of),
];
write.define_public_builtin_instance_methods(PUBLIC_INSTANCE_METHODS);

const PUBLIC_INSTANCE_PROPERTIES: &[(
&'static str,
Option<GenericNativeMethod>,
Option<GenericNativeMethod>,
)] = &[("length", Some(length), Some(set_length))];
write.define_public_builtin_instance_properties(PUBLIC_INSTANCE_PROPERTIES);

const AS3_INSTANCE_METHODS: &[(&'static str, GenericNativeMethod)] = &[
("concat", concat),
("join", join),
("forEach", for_each),
("map", map),
("filter", filter),
("every", every),
("some", some),
("indexOf", index_of),
("lastIndexOf", last_index_of),
("pop", pop),
("push", push),
("reverse", reverse),
("shift", shift),
("unshift", unshift),
("slice", slice),
("splice", splice),
("sort", sort),
("sortOn", sort_on),
];
write.define_as3_builtin_instance_methods(AS3_INSTANCE_METHODS);

const CONSTANTS: &[(&'static str, u32)] = &[
(
"CASEINSENSITIVE",
SortOptions::CASE_INSENSITIVE.bits() as u32,
),
("DESCENDING", SortOptions::DESCENDING.bits() as u32),
("NUMERIC", SortOptions::NUMERIC.bits() as u32),
(
"RETURNINDEXEDARRAY",
SortOptions::RETURN_INDEXED_ARRAY.bits() as u32,
),
("UNIQUESORT", SortOptions::UNIQUE_SORT.bits() as u32),
];
write.define_public_constant_uint_class_traits(CONSTANTS);

class
}
13 changes: 2 additions & 11 deletions core/src/avm2/globals/flash/display/actionscriptversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::method::Method;
use crate::avm2::names::{Namespace, QName};
use crate::avm2::object::Object;
use crate::avm2::traits::Trait;
use crate::avm2::value::Value;
use crate::avm2::Error;
use gc_arena::{GcCell, MutationContext};
Expand Down Expand Up @@ -46,16 +45,8 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>

write.set_attributes(ClassAttributes::FINAL | ClassAttributes::SEALED);

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "ACTIONSCRIPT2"),
QName::new(Namespace::public(), "uint").into(),
Some(2.into()),
));
write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "ACTIONSCRIPT3"),
QName::new(Namespace::public(), "uint").into(),
Some(3.into()),
));
const CONSTANTS: &[(&'static str, u32)] = &[("ACTIONSCRIPT2", 2), ("ACTIONSCRIPT3", 3)];
write.define_public_constant_uint_class_traits(CONSTANTS);

class
}
20 changes: 3 additions & 17 deletions core/src/avm2/globals/flash/display/capsstyle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::method::Method;
use crate::avm2::names::{Namespace, QName};
use crate::avm2::object::Object;
use crate::avm2::traits::Trait;
use crate::avm2::value::Value;
use crate::avm2::Error;
use gc_arena::{GcCell, MutationContext};
Expand Down Expand Up @@ -45,22 +44,9 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
let mut write = class.write(mc);

write.set_attributes(ClassAttributes::SEALED);

write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "NONE"),
QName::new(Namespace::public(), "String").into(),
Some("none".into()),
));
write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "ROUND"),
QName::new(Namespace::public(), "String").into(),
Some("round".into()),
));
write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "SQUARE"),
QName::new(Namespace::public(), "String").into(),
Some("square".into()),
));
const CONSTANTS: &[(&'static str, &'static str)] =
&[("NONE", "none"), ("ROUND", "round"), ("SQUARE", "square")];
write.define_public_constant_string_class_traits(CONSTANTS);

class
}
Loading

0 comments on commit 46ddb9b

Please sign in to comment.