avm2: Split out enumerant values into a separate method as well.

This commit is contained in:
David Wendt 2021-11-05 21:42:01 -04:00 committed by kmeisthax
parent 297526269c
commit 4289f89350
5 changed files with 31 additions and 22 deletions

View File

@ -2502,13 +2502,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let cur_index = self.context.avm2.pop().coerce_to_number(self)?;
let object = self.context.avm2.pop().coerce_to_object(self)?;
let name = object.get_enumerant_name(cur_index as u32);
let value = if let Some(name) = name {
let name = name.coerce_to_string(self)?;
object.get_property(object, &QName::dynamic_name(name).into(), self)?
} else {
Value::Undefined
};
let value = object.get_enumerant_value(cur_index as u32, self)?;
self.context.avm2.push(value);

View File

@ -794,7 +794,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Repeated calls to this function with prior return values must
/// eventually return `None`. Furthermore, returning `0`, while valid, is
/// treated by AVM2 code as signalling `None`.
fn get_next_enumerant(&self, last_index: u32) -> Option<u32> {
fn get_next_enumerant(self, last_index: u32) -> Option<u32> {
let base = self.base();
base.get_next_enumerant(last_index)
@ -802,19 +802,34 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Retrieve a given enumerable name by index.
///
/// Enumerants are listed by index, starting from zero. A value of `None`
/// indicates that no enumerant with that index, or any greater index,
/// exists. (In other words, it means stop.)
///
/// Objects are responsible for maintaining a consistently ordered and
/// indexed list of enumerable names which can be queried by this
/// mechanism.
fn get_enumerant_name(&self, index: u32) -> Option<Value<'gc>> {
/// Enumerants are listed by index, starting from zero and iterated via
/// `get_next_enumerant`. Only enumerants returned by that function are
/// valid here. A value of `None` indicates that no enumerant with that
/// index exists.
fn get_enumerant_name(self, index: u32) -> Option<Value<'gc>> {
let base = self.base();
base.get_enumerant_name(index)
}
/// Retrieve a given enumerable value by index.
///
/// This default implementation of value retrieval assumes that the names
/// of enumerants are also valid local names in the public namespace.
fn get_enumerant_value(
self,
index: u32,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> {
let name = self.get_enumerant_name(index);
if let Some(name) = name {
let name = name.coerce_to_string(activation)?;
Ok(self.get_property(self.into(), &QName::dynamic_name(name).into(), activation)?)
} else {
Ok(Value::Undefined)
}
}
/// Determine if a property is currently enumerable.
///
/// Properties that do not exist are also not enumerable.

View File

@ -199,7 +199,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
self.0.read().base.resolve_any(local_name)
}
fn get_next_enumerant(&self, last_index: u32) -> Option<u32> {
fn get_next_enumerant(self, last_index: u32) -> Option<u32> {
let read = self.0.read();
let last_enumerant = read.base.get_last_enumerant();
let array_length = read.array.length() as u32;
@ -211,7 +211,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
}
}
fn get_enumerant_name(&self, index: u32) -> Option<Value<'gc>> {
fn get_enumerant_name(self, index: u32) -> Option<Value<'gc>> {
let arr_len = self.0.read().array.length() as u32;
if arr_len >= index {
index.checked_sub(1).map(|index| index.into())

View File

@ -111,7 +111,7 @@ impl<'gc> TObject<'gc> for DictionaryObject<'gc> {
Some(self)
}
fn get_next_enumerant(&self, last_index: u32) -> Option<u32> {
fn get_next_enumerant(self, last_index: u32) -> Option<u32> {
let read = self.0.read();
let last_enumerant = read.base.get_last_enumerant();
let object_space_length = read.object_space.keys().len() as u32;
@ -123,7 +123,7 @@ impl<'gc> TObject<'gc> for DictionaryObject<'gc> {
}
}
fn get_enumerant_name(&self, index: u32) -> Option<Value<'gc>> {
fn get_enumerant_name(self, index: u32) -> Option<Value<'gc>> {
let read = self.0.read();
let last_enumerant = read.base.get_last_enumerant();

View File

@ -227,7 +227,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
self.0.read().base.resolve_any(local_name)
}
fn get_next_enumerant(&self, last_index: u32) -> Option<u32> {
fn get_next_enumerant(self, last_index: u32) -> Option<u32> {
if last_index < self.0.read().vector.length() as u32 {
Some(last_index.saturating_add(1))
} else {
@ -235,7 +235,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
}
}
fn get_enumerant_name(&self, index: u32) -> Option<Value<'gc>> {
fn get_enumerant_name(self, index: u32) -> Option<Value<'gc>> {
if self.0.read().vector.length() as u32 >= index {
index.checked_sub(1).map(|index| index.into())
} else {