avm2: Implement WeakObject

This also adds a new required function to TObject called `downgrade`, that will convert the `Object` to a `WeakObject`.
This commit is contained in:
EmperorBale 2023-03-13 22:31:34 -07:00 committed by Bale
parent 5e20b079d9
commit 4815ca5e90
2 changed files with 184 additions and 35 deletions

View File

@ -62,40 +62,70 @@ mod vertex_buffer_3d_object;
mod xml_list_object;
mod xml_object;
pub use crate::avm2::object::array_object::{array_allocator, ArrayObject};
pub use crate::avm2::object::bitmapdata_object::{bitmap_data_allocator, BitmapDataObject};
pub use crate::avm2::object::bytearray_object::{byte_array_allocator, ByteArrayObject};
pub use crate::avm2::object::class_object::ClassObject;
pub use crate::avm2::object::context3d_object::Context3DObject;
pub use crate::avm2::object::date_object::{date_allocator, DateObject};
pub use crate::avm2::object::dictionary_object::{dictionary_allocator, DictionaryObject};
pub use crate::avm2::object::dispatch_object::DispatchObject;
pub use crate::avm2::object::domain_object::{application_domain_allocator, DomainObject};
pub use crate::avm2::object::error_object::{error_allocator, ErrorObject};
pub use crate::avm2::object::event_object::{event_allocator, EventObject};
pub use crate::avm2::object::function_object::{function_allocator, FunctionObject};
pub use crate::avm2::object::index_buffer_3d_object::IndexBuffer3DObject;
pub use crate::avm2::object::loaderinfo_object::{
loader_info_allocator, LoaderInfoObject, LoaderStream,
pub use crate::avm2::object::array_object::{array_allocator, ArrayObject, ArrayObjectWeak};
pub use crate::avm2::object::bitmapdata_object::{
bitmap_data_allocator, BitmapDataObject, BitmapDataObjectWeak,
};
pub use crate::avm2::object::namespace_object::{namespace_allocator, NamespaceObject};
pub use crate::avm2::object::netstream_object::{netstream_allocator, NetStreamObject};
pub use crate::avm2::object::primitive_object::{primitive_allocator, PrimitiveObject};
pub use crate::avm2::object::program_3d_object::Program3DObject;
pub use crate::avm2::object::proxy_object::{proxy_allocator, ProxyObject};
pub use crate::avm2::object::qname_object::{q_name_allocator, QNameObject};
pub use crate::avm2::object::regexp_object::{reg_exp_allocator, RegExpObject};
pub use crate::avm2::object::script_object::{ScriptObject, ScriptObjectData};
pub use crate::avm2::object::sound_object::{sound_allocator, QueuedPlay, SoundData, SoundObject};
pub use crate::avm2::object::soundchannel_object::{sound_channel_allocator, SoundChannelObject};
pub use crate::avm2::object::stage3d_object::{stage_3d_allocator, Stage3DObject};
pub use crate::avm2::object::stage_object::StageObject;
pub use crate::avm2::object::textformat_object::{textformat_allocator, TextFormatObject};
pub use crate::avm2::object::texture_object::TextureObject;
pub use crate::avm2::object::vector_object::{vector_allocator, VectorObject};
pub use crate::avm2::object::vertex_buffer_3d_object::VertexBuffer3DObject;
pub use crate::avm2::object::xml_list_object::{xml_list_allocator, E4XOrXml, XmlListObject};
pub use crate::avm2::object::xml_object::{xml_allocator, XmlObject};
pub use crate::avm2::object::bytearray_object::{
byte_array_allocator, ByteArrayObject, ByteArrayObjectWeak,
};
pub use crate::avm2::object::class_object::{ClassObject, ClassObjectWeak};
pub use crate::avm2::object::context3d_object::{Context3DObject, Context3DObjectWeak};
pub use crate::avm2::object::date_object::{date_allocator, DateObject, DateObjectWeak};
pub use crate::avm2::object::dictionary_object::{
dictionary_allocator, DictionaryObject, DictionaryObjectWeak,
};
pub use crate::avm2::object::dispatch_object::{DispatchObject, DispatchObjectWeak};
pub use crate::avm2::object::domain_object::{
application_domain_allocator, DomainObject, DomainObjectWeak,
};
pub use crate::avm2::object::error_object::{error_allocator, ErrorObject, ErrorObjectWeak};
pub use crate::avm2::object::event_object::{event_allocator, EventObject, EventObjectWeak};
pub use crate::avm2::object::function_object::{
function_allocator, FunctionObject, FunctionObjectWeak,
};
pub use crate::avm2::object::index_buffer_3d_object::{
IndexBuffer3DObject, IndexBuffer3DObjectWeak,
};
pub use crate::avm2::object::loaderinfo_object::{
loader_info_allocator, LoaderInfoObject, LoaderInfoObjectWeak, LoaderStream,
};
pub use crate::avm2::object::namespace_object::{
namespace_allocator, NamespaceObject, NamespaceObjectWeak,
};
pub use crate::avm2::object::netstream_object::{
netstream_allocator, NetStreamObject, NetStreamObjectWeak,
};
pub use crate::avm2::object::primitive_object::{
primitive_allocator, PrimitiveObject, PrimitiveObjectWeak,
};
pub use crate::avm2::object::program_3d_object::{Program3DObject, Program3DObjectWeak};
pub use crate::avm2::object::proxy_object::{proxy_allocator, ProxyObject, ProxyObjectWeak};
pub use crate::avm2::object::qname_object::{q_name_allocator, QNameObject, QNameObjectWeak};
pub use crate::avm2::object::regexp_object::{reg_exp_allocator, RegExpObject, RegExpObjectWeak};
pub use crate::avm2::object::script_object::{ScriptObject, ScriptObjectData, ScriptObjectWeak};
pub use crate::avm2::object::sound_object::{
sound_allocator, QueuedPlay, SoundData, SoundObject, SoundObjectWeak,
};
pub use crate::avm2::object::soundchannel_object::{
sound_channel_allocator, SoundChannelObject, SoundChannelObjectWeak,
};
pub use crate::avm2::object::stage3d_object::{
stage_3d_allocator, Stage3DObject, Stage3DObjectWeak,
};
pub use crate::avm2::object::stage_object::{StageObject, StageObjectWeak};
pub use crate::avm2::object::textformat_object::{
textformat_allocator, TextFormatObject, TextFormatObjectWeak,
};
pub use crate::avm2::object::texture_object::{TextureObject, TextureObjectWeak};
pub use crate::avm2::object::vector_object::{vector_allocator, VectorObject, VectorObjectWeak};
pub use crate::avm2::object::vertex_buffer_3d_object::{
VertexBuffer3DObject, VertexBuffer3DObjectWeak,
};
pub use crate::avm2::object::xml_list_object::{
xml_list_allocator, E4XOrXml, XmlListObject, XmlListObjectWeak,
};
pub use crate::avm2::object::xml_object::{xml_allocator, XmlObject, XmlObjectWeak};
/// Represents an object that can be directly interacted with by the AVM2
/// runtime.
@ -1320,6 +1350,44 @@ impl<'gc> Object<'gc> {
pub fn ptr_eq<T: TObject<'gc>>(a: T, b: T) -> bool {
a.as_ptr() == b.as_ptr()
}
#[rustfmt::skip]
pub fn downgrade(&self) -> WeakObject<'gc> {
match self {
Self::ScriptObject(o) => WeakObject::ScriptObject(ScriptObjectWeak(GcCell::downgrade(o.0))),
Self::FunctionObject(o) => WeakObject::FunctionObject(FunctionObjectWeak(GcCell::downgrade(o.0))),
Self::PrimitiveObject(o) => WeakObject::PrimitiveObject(PrimitiveObjectWeak(GcCell::downgrade(o.0))),
Self::NamespaceObject(o) => WeakObject::NamespaceObject(NamespaceObjectWeak(GcCell::downgrade(o.0))),
Self::ArrayObject(o) => WeakObject::ArrayObject(ArrayObjectWeak(GcCell::downgrade(o.0))),
Self::StageObject(o) => WeakObject::StageObject(StageObjectWeak(GcCell::downgrade(o.0))),
Self::DomainObject(o) => WeakObject::DomainObject(DomainObjectWeak(GcCell::downgrade(o.0))),
Self::EventObject(o) => WeakObject::EventObject(EventObjectWeak(GcCell::downgrade(o.0))),
Self::DispatchObject(o) => WeakObject::DispatchObject(DispatchObjectWeak(GcCell::downgrade(o.0))),
Self::XmlObject(o) => WeakObject::XmlObject(XmlObjectWeak(GcCell::downgrade(o.0))),
Self::XmlListObject(o) => WeakObject::XmlListObject(XmlListObjectWeak(GcCell::downgrade(o.0))),
Self::RegExpObject(o) => WeakObject::RegExpObject(RegExpObjectWeak(GcCell::downgrade(o.0))),
Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(GcCell::downgrade(o.0))),
Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(GcCell::downgrade(o.0))),
Self::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(GcCell::downgrade(o.0))),
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(GcCell::downgrade(o.0))),
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(GcCell::downgrade(o.0))),
Self::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::downgrade(o.0))),
Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(GcCell::downgrade(o.0))),
Self::DateObject(o) => WeakObject::DateObject(DateObjectWeak(GcCell::downgrade(o.0))),
Self::DictionaryObject(o) => WeakObject::DictionaryObject(DictionaryObjectWeak(GcCell::downgrade(o.0))),
Self::QNameObject(o) => WeakObject::QNameObject(QNameObjectWeak(GcCell::downgrade(o.0))),
Self::TextFormatObject(o) => WeakObject::TextFormatObject(TextFormatObjectWeak(GcCell::downgrade(o.0))),
Self::ProxyObject(o) => WeakObject::ProxyObject(ProxyObjectWeak(GcCell::downgrade(o.0))),
Self::ErrorObject(o) => WeakObject::ErrorObject(ErrorObjectWeak(GcCell::downgrade(o.0))),
Self::Stage3DObject(o) => WeakObject::Stage3DObject(Stage3DObjectWeak(GcCell::downgrade(o.0))),
Self::Context3DObject(o) => WeakObject::Context3DObject(Context3DObjectWeak(GcCell::downgrade(o.0))),
Self::IndexBuffer3DObject(o) => WeakObject::IndexBuffer3DObject(IndexBuffer3DObjectWeak(GcCell::downgrade(o.0))),
Self::VertexBuffer3DObject(o) => WeakObject::VertexBuffer3DObject(VertexBuffer3DObjectWeak(GcCell::downgrade(o.0))),
Self::TextureObject(o) => WeakObject::TextureObject(TextureObjectWeak(GcCell::downgrade(o.0))),
Self::Program3DObject(o) => WeakObject::Program3DObject(Program3DObjectWeak(GcCell::downgrade(o.0))),
Self::NetStreamObject(o) => WeakObject::NetStreamObject(NetStreamObjectWeak(GcCell::downgrade(o.0))),
}
}
}
impl<'gc> PartialEq for Object<'gc> {
@ -1335,3 +1403,80 @@ impl<'gc> Hash for Object<'gc> {
self.as_ptr().hash(state);
}
}
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Collect, Debug, Copy)]
#[collect(no_drop)]
pub enum WeakObject<'gc> {
ScriptObject(ScriptObjectWeak<'gc>),
FunctionObject(FunctionObjectWeak<'gc>),
PrimitiveObject(PrimitiveObjectWeak<'gc>),
NamespaceObject(NamespaceObjectWeak<'gc>),
ArrayObject(ArrayObjectWeak<'gc>),
StageObject(StageObjectWeak<'gc>),
DomainObject(DomainObjectWeak<'gc>),
EventObject(EventObjectWeak<'gc>),
DispatchObject(DispatchObjectWeak<'gc>),
XmlObject(XmlObjectWeak<'gc>),
XmlListObject(XmlListObjectWeak<'gc>),
RegExpObject(RegExpObjectWeak<'gc>),
ByteArrayObject(ByteArrayObjectWeak<'gc>),
LoaderInfoObject(LoaderInfoObjectWeak<'gc>),
ClassObject(ClassObjectWeak<'gc>),
VectorObject(VectorObjectWeak<'gc>),
SoundObject(SoundObjectWeak<'gc>),
SoundChannelObject(SoundChannelObjectWeak<'gc>),
BitmapDataObject(BitmapDataObjectWeak<'gc>),
DateObject(DateObjectWeak<'gc>),
DictionaryObject(DictionaryObjectWeak<'gc>),
QNameObject(QNameObjectWeak<'gc>),
TextFormatObject(TextFormatObjectWeak<'gc>),
ProxyObject(ProxyObjectWeak<'gc>),
ErrorObject(ErrorObjectWeak<'gc>),
Stage3DObject(Stage3DObjectWeak<'gc>),
Context3DObject(Context3DObjectWeak<'gc>),
IndexBuffer3DObject(IndexBuffer3DObjectWeak<'gc>),
VertexBuffer3DObject(VertexBuffer3DObjectWeak<'gc>),
TextureObject(TextureObjectWeak<'gc>),
Program3DObject(Program3DObjectWeak<'gc>),
NetStreamObject(NetStreamObjectWeak<'gc>),
}
impl<'gc> WeakObject<'gc> {
pub fn upgrade(self, mc: MutationContext<'gc, '_>) -> Option<Object<'gc>> {
Some(match self {
Self::ScriptObject(o) => ScriptObject(o.0.upgrade(mc)?).into(),
Self::FunctionObject(o) => FunctionObject(o.0.upgrade(mc)?).into(),
Self::PrimitiveObject(o) => PrimitiveObject(o.0.upgrade(mc)?).into(),
Self::NamespaceObject(o) => NamespaceObject(o.0.upgrade(mc)?).into(),
Self::ArrayObject(o) => ArrayObject(o.0.upgrade(mc)?).into(),
Self::StageObject(o) => StageObject(o.0.upgrade(mc)?).into(),
Self::DomainObject(o) => DomainObject(o.0.upgrade(mc)?).into(),
Self::EventObject(o) => EventObject(o.0.upgrade(mc)?).into(),
Self::DispatchObject(o) => DispatchObject(o.0.upgrade(mc)?).into(),
Self::XmlObject(o) => XmlObject(o.0.upgrade(mc)?).into(),
Self::XmlListObject(o) => XmlListObject(o.0.upgrade(mc)?).into(),
Self::RegExpObject(o) => RegExpObject(o.0.upgrade(mc)?).into(),
Self::ByteArrayObject(o) => ByteArrayObject(o.0.upgrade(mc)?).into(),
Self::LoaderInfoObject(o) => LoaderInfoObject(o.0.upgrade(mc)?).into(),
Self::ClassObject(o) => ClassObject(o.0.upgrade(mc)?).into(),
Self::VectorObject(o) => VectorObject(o.0.upgrade(mc)?).into(),
Self::SoundObject(o) => SoundObject(o.0.upgrade(mc)?).into(),
Self::SoundChannelObject(o) => SoundChannelObject(o.0.upgrade(mc)?).into(),
Self::BitmapDataObject(o) => BitmapDataObject(o.0.upgrade(mc)?).into(),
Self::DateObject(o) => DateObject(o.0.upgrade(mc)?).into(),
Self::DictionaryObject(o) => DictionaryObject(o.0.upgrade(mc)?).into(),
Self::QNameObject(o) => QNameObject(o.0.upgrade(mc)?).into(),
Self::TextFormatObject(o) => TextFormatObject(o.0.upgrade(mc)?).into(),
Self::ProxyObject(o) => ProxyObject(o.0.upgrade(mc)?).into(),
Self::ErrorObject(o) => ErrorObject(o.0.upgrade(mc)?).into(),
Self::Stage3DObject(o) => Stage3DObject(o.0.upgrade(mc)?).into(),
Self::Context3DObject(o) => Context3DObject(o.0.upgrade(mc)?).into(),
Self::IndexBuffer3DObject(o) => IndexBuffer3DObject(o.0.upgrade(mc)?).into(),
Self::VertexBuffer3DObject(o) => VertexBuffer3DObject(o.0.upgrade(mc)?).into(),
Self::TextureObject(o) => TextureObject(o.0.upgrade(mc)?).into(),
Self::Program3DObject(o) => Program3DObject(o.0.upgrade(mc)?).into(),
Self::NetStreamObject(o) => NetStreamObject(o.0.upgrade(mc)?).into(),
})
}
}

View File

@ -6,7 +6,7 @@ use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::streams::NetStream;
use gc_arena::{Collect, GcCell, MutationContext};
use gc_arena::{Collect, GcCell, GcWeakCell, MutationContext};
use std::cell::{Ref, RefMut};
use std::fmt::Debug;
@ -28,7 +28,11 @@ pub fn netstream_allocator<'gc>(
#[derive(Clone, Collect, Copy)]
#[collect(no_drop)]
pub struct NetStreamObject<'gc>(GcCell<'gc, NetStreamObjectData<'gc>>);
pub struct NetStreamObject<'gc>(pub GcCell<'gc, NetStreamObjectData<'gc>>);
#[derive(Collect, Clone, Copy, Debug)]
#[collect(no_drop)]
pub struct NetStreamObjectWeak<'gc>(pub GcWeakCell<'gc, NetStreamObjectData<'gc>>);
#[derive(Clone, Collect)]
#[collect(no_drop)]