avm2: Use `Gc` instead of `GcCell` in `VectorObject`
This commit is contained in:
parent
b1acb17806
commit
562be06fb1
|
@ -1391,7 +1391,7 @@ impl<'gc> Object<'gc> {
|
||||||
Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(Gc::downgrade(o.0))),
|
Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(Gc::downgrade(o.0))),
|
||||||
Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(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::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(GcCell::downgrade(o.0))),
|
||||||
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(GcCell::downgrade(o.0))),
|
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(Gc::downgrade(o.0))),
|
||||||
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(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::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::downgrade(o.0))),
|
||||||
Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))),
|
Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))),
|
||||||
|
|
|
@ -8,7 +8,8 @@ use crate::avm2::vector::VectorStorage;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use crate::avm2::Multiname;
|
use crate::avm2::Multiname;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
|
use gc_arena::barrier::unlock;
|
||||||
|
use gc_arena::{lock::RefLock, Collect, Gc, GcWeak, Mutation};
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
|
|
||||||
/// A class instance allocator that allocates Vector objects.
|
/// A class instance allocator that allocates Vector objects.
|
||||||
|
@ -16,18 +17,18 @@ pub fn vector_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 base = ScriptObjectData::new(class);
|
let base = ScriptObjectData::new(class).into();
|
||||||
|
|
||||||
let param_type = class
|
let param_type = class
|
||||||
.inner_class_definition()
|
.inner_class_definition()
|
||||||
.param()
|
.param()
|
||||||
.ok_or("Cannot convert to unparametrized Vector")?;
|
.ok_or("Cannot convert to unparametrized Vector")?;
|
||||||
|
|
||||||
Ok(VectorObject(GcCell::new(
|
Ok(VectorObject(Gc::new(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
VectorObjectData {
|
VectorObjectData {
|
||||||
base,
|
base,
|
||||||
vector: VectorStorage::new(0, false, param_type, activation),
|
vector: RefLock::new(VectorStorage::new(0, false, param_type, activation)),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.into())
|
.into())
|
||||||
|
@ -36,16 +37,16 @@ pub fn vector_allocator<'gc>(
|
||||||
/// An Object which stores typed properties in vector storage
|
/// An Object which stores typed properties in vector storage
|
||||||
#[derive(Collect, Clone, Copy)]
|
#[derive(Collect, Clone, Copy)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct VectorObject<'gc>(pub GcCell<'gc, VectorObjectData<'gc>>);
|
pub struct VectorObject<'gc>(pub Gc<'gc, VectorObjectData<'gc>>);
|
||||||
|
|
||||||
#[derive(Collect, Clone, Copy, Debug)]
|
#[derive(Collect, Clone, Copy, Debug)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct VectorObjectWeak<'gc>(pub GcWeakCell<'gc, VectorObjectData<'gc>>);
|
pub struct VectorObjectWeak<'gc>(pub GcWeak<'gc, VectorObjectData<'gc>>);
|
||||||
|
|
||||||
impl fmt::Debug for VectorObject<'_> {
|
impl fmt::Debug for VectorObject<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("VectorObject")
|
f.debug_struct("VectorObject")
|
||||||
.field("ptr", &self.0.as_ptr())
|
.field("ptr", &Gc::as_ptr(self.0))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,10 +55,10 @@ impl fmt::Debug for VectorObject<'_> {
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct VectorObjectData<'gc> {
|
pub struct VectorObjectData<'gc> {
|
||||||
/// Base script object
|
/// Base script object
|
||||||
base: ScriptObjectData<'gc>,
|
base: RefLock<ScriptObjectData<'gc>>,
|
||||||
|
|
||||||
/// Vector-structured properties
|
/// Vector-structured properties
|
||||||
vector: VectorStorage<'gc>,
|
vector: RefLock<VectorStorage<'gc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> VectorObject<'gc> {
|
impl<'gc> VectorObject<'gc> {
|
||||||
|
@ -71,11 +72,11 @@ impl<'gc> VectorObject<'gc> {
|
||||||
|
|
||||||
let applied_class = vector_class.parametrize(activation, value_type)?;
|
let applied_class = vector_class.parametrize(activation, value_type)?;
|
||||||
|
|
||||||
let object: Object<'gc> = VectorObject(GcCell::new(
|
let object: Object<'gc> = VectorObject(Gc::new(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
VectorObjectData {
|
VectorObjectData {
|
||||||
base: ScriptObjectData::new(applied_class),
|
base: ScriptObjectData::new(applied_class).into(),
|
||||||
vector,
|
vector: RefLock::new(vector),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.into();
|
.into();
|
||||||
|
@ -88,15 +89,15 @@ impl<'gc> VectorObject<'gc> {
|
||||||
|
|
||||||
impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
fn base(&self) -> Ref<ScriptObjectData<'gc>> {
|
fn base(&self) -> Ref<ScriptObjectData<'gc>> {
|
||||||
Ref::map(self.0.read(), |read| &read.base)
|
self.0.base.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> {
|
fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> {
|
||||||
RefMut::map(self.0.write(mc), |write| &mut write.base)
|
unlock!(Gc::write(mc, self.0), VectorObjectData, base).borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ptr(&self) -> *const ObjectPtr {
|
fn as_ptr(&self) -> *const ObjectPtr {
|
||||||
self.0.as_ptr() as *const ObjectPtr
|
Gc::as_ptr(self.0) as *const ObjectPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_property_local(
|
fn get_property_local(
|
||||||
|
@ -104,21 +105,19 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
name: &Multiname<'gc>,
|
name: &Multiname<'gc>,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
let read = self.0.read();
|
|
||||||
|
|
||||||
if name.contains_public_namespace() {
|
if name.contains_public_namespace() {
|
||||||
if let Some(name) = name.local_name() {
|
if let Some(name) = name.local_name() {
|
||||||
if let Ok(index) = name.parse::<usize>() {
|
if let Ok(index) = name.parse::<usize>() {
|
||||||
return read.vector.get(index, activation);
|
return self.0.vector.borrow().get(index, activation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read.base.get_property_local(name, activation)
|
self.0.base.borrow().get_property_local(name, activation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_index_property(self, index: usize) -> Option<Value<'gc>> {
|
fn get_index_property(self, index: usize) -> Option<Value<'gc>> {
|
||||||
self.0.read().vector.get_optional(index)
|
self.0.vector.borrow().get_optional(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_property_local(
|
fn set_property_local(
|
||||||
|
@ -127,19 +126,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
value: Value<'gc>,
|
value: Value<'gc>,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
|
let mc = activation.context.gc_context;
|
||||||
|
|
||||||
if name.contains_public_namespace() {
|
if name.contains_public_namespace() {
|
||||||
if let Some(name) = name.local_name() {
|
if let Some(name) = name.local_name() {
|
||||||
if let Ok(index) = name.parse::<usize>() {
|
if let Ok(index) = name.parse::<usize>() {
|
||||||
let type_of = self.0.read().vector.value_type_for_coercion(activation);
|
let type_of = self.0.vector.borrow().value_type_for_coercion(activation);
|
||||||
let value = match value.coerce_to_type(activation, type_of)? {
|
let value = match value.coerce_to_type(activation, type_of)? {
|
||||||
Value::Undefined => self.0.read().vector.default(activation),
|
Value::Undefined => self.0.vector.borrow().default(activation),
|
||||||
Value::Null => self.0.read().vector.default(activation),
|
Value::Null => self.0.vector.borrow().default(activation),
|
||||||
v => v,
|
v => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.0
|
unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
|
||||||
.write(activation.context.gc_context)
|
.borrow_mut()
|
||||||
.vector
|
|
||||||
.set(index, value, activation)?;
|
.set(index, value, activation)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -147,9 +147,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut write = self.0.write(activation.context.gc_context);
|
unlock!(Gc::write(mc, self.0), VectorObjectData, base)
|
||||||
|
.borrow_mut()
|
||||||
write.base.set_property_local(name, value, activation)
|
.set_property_local(name, value, activation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_property_local(
|
fn init_property_local(
|
||||||
|
@ -158,19 +158,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
value: Value<'gc>,
|
value: Value<'gc>,
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
|
let mc = activation.context.gc_context;
|
||||||
|
|
||||||
if name.contains_public_namespace() {
|
if name.contains_public_namespace() {
|
||||||
if let Some(name) = name.local_name() {
|
if let Some(name) = name.local_name() {
|
||||||
if let Ok(index) = name.parse::<usize>() {
|
if let Ok(index) = name.parse::<usize>() {
|
||||||
let type_of = self.0.read().vector.value_type_for_coercion(activation);
|
let type_of = self.0.vector.borrow().value_type_for_coercion(activation);
|
||||||
let value = match value.coerce_to_type(activation, type_of)? {
|
let value = match value.coerce_to_type(activation, type_of)? {
|
||||||
Value::Undefined => self.0.read().vector.default(activation),
|
Value::Undefined => self.0.vector.borrow().default(activation),
|
||||||
Value::Null => self.0.read().vector.default(activation),
|
Value::Null => self.0.vector.borrow().default(activation),
|
||||||
v => v,
|
v => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.0
|
unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
|
||||||
.write(activation.context.gc_context)
|
.borrow_mut()
|
||||||
.vector
|
|
||||||
.set(index, value, activation)?;
|
.set(index, value, activation)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -178,9 +179,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut write = self.0.write(activation.context.gc_context);
|
unlock!(Gc::write(mc, self.0), VectorObjectData, base)
|
||||||
|
.borrow_mut()
|
||||||
write.base.init_property_local(name, value, activation)
|
.init_property_local(name, value, activation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_property_local(
|
fn delete_property_local(
|
||||||
|
@ -188,6 +189,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
name: &Multiname<'gc>,
|
name: &Multiname<'gc>,
|
||||||
) -> Result<bool, Error<'gc>> {
|
) -> Result<bool, Error<'gc>> {
|
||||||
|
let mc = activation.context.gc_context;
|
||||||
|
|
||||||
if name.contains_public_namespace()
|
if name.contains_public_namespace()
|
||||||
&& name.local_name().is_some()
|
&& name.local_name().is_some()
|
||||||
&& name.local_name().unwrap().parse::<usize>().is_ok()
|
&& name.local_name().unwrap().parse::<usize>().is_ok()
|
||||||
|
@ -195,10 +198,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self
|
Ok(unlock!(Gc::write(mc, self.0), VectorObjectData, base)
|
||||||
.0
|
.borrow_mut()
|
||||||
.write(activation.context.gc_context)
|
|
||||||
.base
|
|
||||||
.delete_property_local(name))
|
.delete_property_local(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,12 +207,12 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
if name.contains_public_namespace() {
|
if name.contains_public_namespace() {
|
||||||
if let Some(name) = name.local_name() {
|
if let Some(name) = name.local_name() {
|
||||||
if let Ok(index) = name.parse::<usize>() {
|
if let Ok(index) = name.parse::<usize>() {
|
||||||
return self.0.read().vector.is_in_range(index);
|
return self.0.vector.borrow().is_in_range(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.0.read().base.has_own_property(name)
|
self.0.base.borrow().has_own_property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_next_enumerant(
|
fn get_next_enumerant(
|
||||||
|
@ -219,7 +220,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
last_index: u32,
|
last_index: u32,
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
) -> Result<Option<u32>, Error<'gc>> {
|
) -> Result<Option<u32>, Error<'gc>> {
|
||||||
if last_index < self.0.read().vector.length() as u32 {
|
if last_index < self.0.vector.borrow().length() as u32 {
|
||||||
Ok(Some(last_index.saturating_add(1)))
|
Ok(Some(last_index.saturating_add(1)))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -231,7 +232,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
index: u32,
|
index: u32,
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if self.0.read().vector.length() as u32 >= index {
|
if self.0.vector.borrow().length() as u32 >= index {
|
||||||
Ok(index
|
Ok(index
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
.map(|index| index.into())
|
.map(|index| index.into())
|
||||||
|
@ -246,10 +247,10 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_vector_storage(&self) -> Option<Ref<VectorStorage<'gc>>> {
|
fn as_vector_storage(&self) -> Option<Ref<VectorStorage<'gc>>> {
|
||||||
Some(Ref::map(self.0.read(), |vod| &vod.vector))
|
Some(self.0.vector.borrow())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_vector_storage_mut(&self, mc: &Mutation<'gc>) -> Option<RefMut<VectorStorage<'gc>>> {
|
fn as_vector_storage_mut(&self, mc: &Mutation<'gc>) -> Option<RefMut<VectorStorage<'gc>>> {
|
||||||
Some(RefMut::map(self.0.write(mc), |vod| &mut vod.vector))
|
Some(unlock!(Gc::write(mc, self.0), VectorObjectData, vector).borrow_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue