avm2: Use SystemClassDefs to look up builtin classes in a few more places

This commit is contained in:
Lord-McSweeney 2024-09-06 10:17:35 -07:00 committed by Lord-McSweeney
parent 96a8fe65b3
commit ee996cd433
12 changed files with 89 additions and 77 deletions

View File

@ -2026,8 +2026,8 @@ impl<'a, 'gc> Activation<'a, 'gc> {
} }
fn op_check_filter(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> { fn op_check_filter(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> {
let xml = self.avm2().classes().xml.inner_class_definition(); let xml = self.avm2().class_defs().xml;
let xml_list = self.avm2().classes().xml_list.inner_class_definition(); let xml_list = self.avm2().class_defs().xml_list;
let value = self.pop_stack().coerce_to_object_or_typeerror(self, None)?; let value = self.pop_stack().coerce_to_object_or_typeerror(self, None)?;
if value.is_of_type(xml) || value.is_of_type(xml_list) { if value.is_of_type(xml) || value.is_of_type(xml_list) {
@ -2748,11 +2748,11 @@ impl<'a, 'gc> Activation<'a, 'gc> {
Value::Bool(_) => "boolean", Value::Bool(_) => "boolean",
Value::Number(_) | Value::Integer(_) => "number", Value::Number(_) | Value::Integer(_) => "number",
Value::Object(o) => { Value::Object(o) => {
let classes = self.avm2().classes(); let classes = self.avm2().class_defs();
match o { match o {
Object::FunctionObject(_) => { Object::FunctionObject(_) => {
if o.instance_class() == classes.function.inner_class_definition() { if o.instance_class() == classes.function {
"function" "function"
} else { } else {
// Subclasses always have a typeof = "object" // Subclasses always have a typeof = "object"
@ -2760,8 +2760,8 @@ impl<'a, 'gc> Activation<'a, 'gc> {
} }
} }
Object::XmlObject(_) | Object::XmlListObject(_) => { Object::XmlObject(_) | Object::XmlListObject(_) => {
if o.instance_class() == classes.xml_list.inner_class_definition() if o.instance_class() == classes.xml_list
|| o.instance_class() == classes.xml.inner_class_definition() || o.instance_class() == classes.xml
{ {
"xml" "xml"
} else { } else {

View File

@ -78,7 +78,7 @@ pub fn serialize_value<'gc>(
} }
} else if let Some(vec) = o.as_vector_storage() { } else if let Some(vec) = o.as_vector_storage() {
let val_type = vec.value_type(); let val_type = vec.value_type();
if val_type == Some(activation.avm2().classes().int.inner_class_definition()) { if val_type == Some(activation.avm2().class_defs().int) {
let int_vec: Vec<_> = vec let int_vec: Vec<_> = vec
.iter() .iter()
.map(|v| { .map(|v| {
@ -87,9 +87,7 @@ pub fn serialize_value<'gc>(
}) })
.collect(); .collect();
Some(AmfValue::VectorInt(int_vec, vec.is_fixed())) Some(AmfValue::VectorInt(int_vec, vec.is_fixed()))
} else if val_type } else if val_type == Some(activation.avm2().class_defs().uint) {
== Some(activation.avm2().classes().uint.inner_class_definition())
{
let uint_vec: Vec<_> = vec let uint_vec: Vec<_> = vec
.iter() .iter()
.map(|v| { .map(|v| {
@ -98,9 +96,7 @@ pub fn serialize_value<'gc>(
}) })
.collect(); .collect();
Some(AmfValue::VectorUInt(uint_vec, vec.is_fixed())) Some(AmfValue::VectorUInt(uint_vec, vec.is_fixed()))
} else if val_type } else if val_type == Some(activation.avm2().class_defs().number) {
== Some(activation.avm2().classes().number.inner_class_definition())
{
let num_vec: Vec<_> = vec let num_vec: Vec<_> = vec
.iter() .iter()
.map(|v| { .map(|v| {
@ -388,7 +384,7 @@ pub fn deserialize_value<'gc>(
let storage = VectorStorage::from_values( let storage = VectorStorage::from_values(
vec.iter().map(|v| (*v).into()).collect(), vec.iter().map(|v| (*v).into()).collect(),
*is_fixed, *is_fixed,
Some(activation.avm2().classes().number.inner_class_definition()), Some(activation.avm2().class_defs().number),
); );
VectorObject::from_vector(storage, activation)?.into() VectorObject::from_vector(storage, activation)?.into()
} }
@ -396,7 +392,7 @@ pub fn deserialize_value<'gc>(
let storage = VectorStorage::from_values( let storage = VectorStorage::from_values(
vec.iter().map(|v| (*v).into()).collect(), vec.iter().map(|v| (*v).into()).collect(),
*is_fixed, *is_fixed,
Some(activation.avm2().classes().uint.inner_class_definition()), Some(activation.avm2().class_defs().uint),
); );
VectorObject::from_vector(storage, activation)?.into() VectorObject::from_vector(storage, activation)?.into()
} }
@ -404,7 +400,7 @@ pub fn deserialize_value<'gc>(
let storage = VectorStorage::from_values( let storage = VectorStorage::from_values(
vec.iter().map(|v| (*v).into()).collect(), vec.iter().map(|v| (*v).into()).collect(),
*is_fixed, *is_fixed,
Some(activation.avm2().classes().int.inner_class_definition()), Some(activation.avm2().class_defs().int),
); );
VectorObject::from_vector(storage, activation)?.into() VectorObject::from_vector(storage, activation)?.into()
} }

View File

@ -180,6 +180,19 @@ pub struct SystemClassDefs<'gc> {
pub function: Class<'gc>, pub function: Class<'gc>,
pub void: Class<'gc>, pub void: Class<'gc>,
pub array: Class<'gc>,
pub boolean: Class<'gc>,
pub int: Class<'gc>,
pub generic_vector: Class<'gc>,
pub namespace: Class<'gc>,
pub number: Class<'gc>,
pub string: Class<'gc>,
pub uint: Class<'gc>,
pub xml: Class<'gc>,
pub xml_list: Class<'gc>,
pub bitmap: Class<'gc>,
pub bitmapdata: Class<'gc>,
pub igraphicsdata: Class<'gc>, pub igraphicsdata: Class<'gc>,
pub graphicsbitmapfill: Class<'gc>, pub graphicsbitmapfill: Class<'gc>,
pub graphicsendfill: Class<'gc>, pub graphicsendfill: Class<'gc>,
@ -323,6 +336,19 @@ impl<'gc> SystemClassDefs<'gc> {
void, void,
// temporary initialization // temporary initialization
array: object,
boolean: object,
int: object,
generic_vector: object,
namespace: object,
number: object,
string: object,
uint: object,
xml: object,
xml_list: object,
bitmap: object,
bitmapdata: object,
igraphicsdata: object, igraphicsdata: object,
graphicsbitmapfill: object, graphicsbitmapfill: object,
graphicsendfill: object, graphicsendfill: object,
@ -448,6 +474,9 @@ macro_rules! avm2_system_class {
let sc = $activation.avm2().system_classes.as_mut().unwrap(); let sc = $activation.avm2().system_classes.as_mut().unwrap();
sc.$field = class_object; sc.$field = class_object;
let scd = $activation.avm2().system_class_defs.as_mut().unwrap();
scd.$field = class_object.inner_class_definition();
}; };
} }
@ -940,6 +969,10 @@ fn load_playerglobal<'gc>(
avm2_system_class_defs_playerglobal!( avm2_system_class_defs_playerglobal!(
&mut *activation, &mut *activation,
[ [
("", "XML", xml),
("", "XMLList", xml_list),
("flash.display", "Bitmap", bitmap),
("flash.display", "BitmapData", bitmapdata),
("flash.display", "IGraphicsData", igraphicsdata), ("flash.display", "IGraphicsData", igraphicsdata),
("flash.display", "GraphicsBitmapFill", graphicsbitmapfill), ("flash.display", "GraphicsBitmapFill", graphicsbitmapfill),
("flash.display", "GraphicsEndFill", graphicsendfill), ("flash.display", "GraphicsEndFill", graphicsendfill),

View File

@ -19,7 +19,7 @@ pub fn bitmap_allocator<'gc>(
class: ClassObject<'gc>, class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<Object<'gc>, Error<'gc>> { ) -> Result<Object<'gc>, Error<'gc>> {
let bitmap_cls = activation.avm2().classes().bitmap.inner_class_definition(); let bitmap_cls = activation.avm2().class_defs().bitmap;
let bitmapdata_cls = activation.context.avm2.classes().bitmapdata; let bitmapdata_cls = activation.context.avm2.classes().bitmapdata;
let mut class_def = Some(class.inner_class_definition()); let mut class_def = Some(class.inner_class_definition());

View File

@ -370,7 +370,7 @@ pub fn get_vector<'gc>(
height, height,
); );
let value_type = activation.avm2().classes().uint.inner_class_definition(); let value_type = activation.avm2().class_defs().uint;
let new_storage = VectorStorage::from_values(pixels, false, Some(value_type)); let new_storage = VectorStorage::from_values(pixels, false, Some(value_type));
return Ok(VectorObject::from_vector(new_storage, activation)?.into()); return Ok(VectorObject::from_vector(new_storage, activation)?.into());

View File

@ -123,7 +123,7 @@ pub fn get_qualified_definition_names<'gc>(
.map(|name| Value::String(name.to_qualified_name(activation.context.gc_context))) .map(|name| Value::String(name.to_qualified_name(activation.context.gc_context)))
.collect(), .collect(),
false, false,
Some(activation.avm2().classes().string.inner_class_definition()), Some(activation.avm2().class_defs().string),
); );
let name_vector = VectorObject::from_vector(storage, activation)?; let name_vector = VectorObject::from_vector(storage, activation)?;

View File

@ -235,13 +235,12 @@ impl<'gc> AvmSerializer<'gc> {
)?)); )?));
} }
self.obj_stack.push(obj); self.obj_stack.push(obj);
let value = let value = if obj.is_of_type(activation.avm2().class_defs().array) {
if obj.is_of_type(activation.avm2().classes().array.inner_class_definition()) { // TODO: Vectors
// TODO: Vectors self.serialize_iterable(activation, obj)?
self.serialize_iterable(activation, obj)? } else {
} else { self.serialize_object(activation, obj)?
self.serialize_object(activation, obj)? };
};
self.obj_stack self.obj_stack
.pop() .pop()
.expect("Stack underflow during JSON serialization"); .expect("Stack underflow during JSON serialization");

View File

@ -126,11 +126,7 @@ impl<'gc> ScriptObject<'gc> {
// can observe (the lack of) it. // can observe (the lack of) it.
let base = ScriptObjectWrapper(Gc::new( let base = ScriptObjectWrapper(Gc::new(
mc, mc,
ScriptObjectData::custom_new( ScriptObjectData::custom_new(activation.avm2().class_defs().object, None, vt),
activation.avm2().classes().object.inner_class_definition(),
None,
vt,
),
)); ));
ScriptObject(base.0).into() ScriptObject(base.0).into()

View File

@ -93,14 +93,14 @@ impl<'gc> OptValue<'gc> {
return true; return true;
} }
let classes = activation.avm2().classes(); let class_defs = activation.avm2().class_defs();
// Primitives are always not-null // Primitives are always not-null
self.class == Some(classes.int.inner_class_definition()) self.class == Some(class_defs.int)
|| self.class == Some(classes.uint.inner_class_definition()) || self.class == Some(class_defs.uint)
|| self.class == Some(classes.number.inner_class_definition()) || self.class == Some(class_defs.number)
|| self.class == Some(classes.boolean.inner_class_definition()) || self.class == Some(class_defs.boolean)
|| self.class == Some(activation.avm2().class_defs().void) || self.class == Some(class_defs.void)
} }
pub fn merged_with(self, other: OptValue<'gc>) -> OptValue<'gc> { pub fn merged_with(self, other: OptValue<'gc>) -> OptValue<'gc> {
@ -332,24 +332,16 @@ pub fn optimize<'gc>(
pub namespace: Class<'gc>, pub namespace: Class<'gc>,
} }
let types = Types { let types = Types {
object: activation.avm2().classes().object.inner_class_definition(), object: activation.avm2().class_defs().object,
int: activation.avm2().classes().int.inner_class_definition(), int: activation.avm2().class_defs().int,
uint: activation.avm2().classes().uint.inner_class_definition(), uint: activation.avm2().class_defs().uint,
number: activation.avm2().classes().number.inner_class_definition(), number: activation.avm2().class_defs().number,
boolean: activation.avm2().classes().boolean.inner_class_definition(), boolean: activation.avm2().class_defs().boolean,
string: activation.avm2().classes().string.inner_class_definition(), string: activation.avm2().class_defs().string,
array: activation.avm2().classes().array.inner_class_definition(), array: activation.avm2().class_defs().array,
function: activation function: activation.avm2().class_defs().function,
.avm2()
.classes()
.function
.inner_class_definition(),
void: activation.avm2().class_defs().void, void: activation.avm2().class_defs().void,
namespace: activation namespace: activation.avm2().class_defs().namespace,
.avm2()
.classes()
.namespace
.inner_class_definition(),
}; };
let method_body = method let method_body = method

View File

@ -990,19 +990,19 @@ impl<'gc> Value<'gc> {
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
class: Class<'gc>, class: Class<'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if class == activation.avm2().classes().int.inner_class_definition() { if class == activation.avm2().class_defs().int {
return Ok(self.coerce_to_i32(activation)?.into()); return Ok(self.coerce_to_i32(activation)?.into());
} }
if class == activation.avm2().classes().uint.inner_class_definition() { if class == activation.avm2().class_defs().uint {
return Ok(self.coerce_to_u32(activation)?.into()); return Ok(self.coerce_to_u32(activation)?.into());
} }
if class == activation.avm2().classes().number.inner_class_definition() { if class == activation.avm2().class_defs().number {
return Ok(self.coerce_to_number(activation)?.into()); return Ok(self.coerce_to_number(activation)?.into());
} }
if class == activation.avm2().classes().boolean.inner_class_definition() { if class == activation.avm2().class_defs().boolean {
return Ok(self.coerce_to_boolean().into()); return Ok(self.coerce_to_boolean().into());
} }
@ -1013,7 +1013,7 @@ impl<'gc> Value<'gc> {
return Ok(Value::Null); return Ok(Value::Null);
} }
if class == activation.avm2().classes().string.inner_class_definition() { if class == activation.avm2().class_defs().string {
return Ok(self.coerce_to_string(activation)?.into()); return Ok(self.coerce_to_string(activation)?.into());
} }
@ -1093,13 +1093,13 @@ impl<'gc> Value<'gc> {
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
type_object: Class<'gc>, type_object: Class<'gc>,
) -> bool { ) -> bool {
if type_object == activation.avm2().classes().number.inner_class_definition() { if type_object == activation.avm2().class_defs().number {
return self.is_number(); return self.is_number();
} }
if type_object == activation.avm2().classes().uint.inner_class_definition() { if type_object == activation.avm2().class_defs().uint {
return self.is_u32(); return self.is_u32();
} }
if type_object == activation.avm2().classes().int.inner_class_definition() { if type_object == activation.avm2().class_defs().int {
return self.is_i32(); return self.is_i32();
} }

View File

@ -118,11 +118,11 @@ impl<'gc> VectorStorage<'gc> {
/// Get the default value for this vector. /// Get the default value for this vector.
pub fn default(&self, activation: &mut Activation<'_, 'gc>) -> Value<'gc> { pub fn default(&self, activation: &mut Activation<'_, 'gc>) -> Value<'gc> {
if let Some(value_type) = self.value_type { if let Some(value_type) = self.value_type {
if value_type == activation.avm2().classes().int.inner_class_definition() if value_type == activation.avm2().class_defs().int
|| value_type == activation.avm2().classes().uint.inner_class_definition() || value_type == activation.avm2().class_defs().uint
{ {
Value::Integer(0) Value::Integer(0)
} else if value_type == activation.avm2().classes().number.inner_class_definition() { } else if value_type == activation.avm2().class_defs().number {
Value::Number(0.0) Value::Number(0.0)
} else { } else {
Value::Null Value::Null
@ -234,11 +234,11 @@ impl<'gc> VectorStorage<'gc> {
if let Some(v) = self.storage.pop() { if let Some(v) = self.storage.pop() {
Ok(v) Ok(v)
} else if let Some(value_type) = self.value_type() { } else if let Some(value_type) = self.value_type() {
if value_type == activation.avm2().classes().uint.inner_class_definition() if value_type == activation.avm2().class_defs().uint
|| value_type == activation.avm2().classes().int.inner_class_definition() || value_type == activation.avm2().class_defs().int
{ {
Ok(Value::Integer(0)) Ok(Value::Integer(0))
} else if value_type == activation.avm2().classes().number.inner_class_definition() { } else if value_type == activation.avm2().class_defs().number {
Ok(Value::Number(0.0)) Ok(Value::Number(0.0))
} else { } else {
Ok(Value::Undefined) Ok(Value::Undefined)
@ -280,11 +280,11 @@ impl<'gc> VectorStorage<'gc> {
if !self.storage.is_empty() { if !self.storage.is_empty() {
Ok(self.storage.remove(0)) Ok(self.storage.remove(0))
} else if let Some(value_type) = self.value_type() { } else if let Some(value_type) = self.value_type() {
if value_type == activation.avm2().classes().uint.inner_class_definition() if value_type == activation.avm2().class_defs().uint
|| value_type == activation.avm2().classes().int.inner_class_definition() || value_type == activation.avm2().class_defs().int
{ {
Ok(Value::Integer(0)) Ok(Value::Integer(0))
} else if value_type == activation.avm2().classes().number.inner_class_definition() { } else if value_type == activation.avm2().class_defs().number {
Ok(Value::Number(0.0)) Ok(Value::Number(0.0))
} else { } else {
Ok(Value::Undefined) Ok(Value::Undefined)

View File

@ -65,13 +65,9 @@ impl<'gc> BitmapClass<'gc> {
context: &mut UpdateContext<'gc>, context: &mut UpdateContext<'gc>,
) -> Option<Self> { ) -> Option<Self> {
let class_definition = class.inner_class_definition(); let class_definition = class.inner_class_definition();
if class_definition if class_definition.has_class_in_chain(context.avm2.class_defs().bitmap) {
.has_class_in_chain(context.avm2.classes().bitmap.inner_class_definition())
{
Some(BitmapClass::Bitmap(class)) Some(BitmapClass::Bitmap(class))
} else if class_definition } else if class_definition.has_class_in_chain(context.avm2.class_defs().bitmapdata) {
.has_class_in_chain(context.avm2.classes().bitmapdata.inner_class_definition())
{
Some(BitmapClass::BitmapData(class)) Some(BitmapClass::BitmapData(class))
} else { } else {
None None