Skip to content

Commit

Permalink
avm2: Change ArrayIter to use get_index_property instead of `get_pu…
Browse files Browse the repository at this point in the history
…blic_property`
  • Loading branch information
Lord-McSweeney authored and torokati44 committed Jan 14, 2025
1 parent c12215b commit 691a35f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 63 deletions.
70 changes: 34 additions & 36 deletions core/src/avm2/globals/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::avm2::activation::Activation;
use crate::avm2::array::ArrayStorage;
use crate::avm2::class::Class;
use crate::avm2::error::range_error;
use crate::avm2::error::{make_error_1125, range_error};
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{array_allocator, ArrayObject, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
Expand Down Expand Up @@ -333,7 +333,7 @@ pub fn to_locale_string<'gc>(
/// array while this happens would cause a panic; this code exists to prevent
/// that.
pub struct ArrayIter<'gc> {
array_object: Value<'gc>,
array_object: Object<'gc>,
pub index: u32,
pub rev_index: u32,
}
Expand All @@ -359,7 +359,7 @@ impl<'gc> ArrayIter<'gc> {
.coerce_to_u32(activation)?;

Ok(Self {
array_object: Value::from(array_object),
array_object,
index: start_index.min(length),
rev_index: end_index.saturating_add(1).min(length),
})
Expand All @@ -372,22 +372,25 @@ impl<'gc> ArrayIter<'gc> {
pub fn next(
&mut self,
activation: &mut Activation<'_, 'gc>,
) -> Option<Result<(u32, Value<'gc>), Error<'gc>>> {
) -> Result<Option<(u32, Value<'gc>)>, Error<'gc>> {
if self.index < self.rev_index {
let i = self.index;

self.index += 1;

Some(
self.array_object
.get_public_property(
AvmString::new_utf8(activation.gc(), i.to_string()),
activation,
)
.map(|val| (i, val)),
)
let val = self.array_object.get_index_property(i as usize);

let val = if let Some(storage) = self.array_object.as_vector_storage() {
// Special case for Vector- it throws an error if trying to access
// an element that was removed
val.ok_or_else(|| make_error_1125(activation, i as usize, storage.length()))?
} else {
val.unwrap_or(Value::Undefined)
};

Ok(Some((i, val)))
} else {
None
Ok(None)
}
}

Expand All @@ -398,22 +401,25 @@ impl<'gc> ArrayIter<'gc> {
pub fn next_back(
&mut self,
activation: &mut Activation<'_, 'gc>,
) -> Option<Result<(u32, Value<'gc>), Error<'gc>>> {
) -> Result<Option<(u32, Value<'gc>)>, Error<'gc>> {
if self.index < self.rev_index {
self.rev_index -= 1;

let i = self.rev_index;

Some(
self.array_object
.get_public_property(
AvmString::new_utf8(activation.gc(), i.to_string()),
activation,
)
.map(|val| (i, val)),
)
let val = self.array_object.get_index_property(i as usize);

let val = if let Some(storage) = self.array_object.as_vector_storage() {
// Special case for Vector- it throws an error if trying to access
// an element that was removed
val.ok_or_else(|| make_error_1125(activation, i as usize, storage.length()))?
} else {
val.unwrap_or(Value::Undefined)
};

Ok(Some((i, val)))
} else {
None
Ok(None)
}
}
}
Expand All @@ -430,9 +436,7 @@ pub fn for_each<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
callback.call(activation, receiver, &[item, i.into(), this.into()])?;
}

Expand All @@ -452,8 +456,7 @@ pub fn map<'gc>(
let mut new_array = ArrayStorage::new(0);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;
while let Some((i, item)) = iter.next(activation)? {
let new_item = callback.call(activation, receiver, &[item, i.into(), this.into()])?;

new_array.push(new_item);
Expand All @@ -475,8 +478,7 @@ pub fn filter<'gc>(
let mut new_array = ArrayStorage::new(0);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;
while let Some((i, item)) = iter.next(activation)? {
let is_allowed = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand All @@ -501,9 +503,7 @@ pub fn every<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let result = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand All @@ -528,9 +528,7 @@ pub fn some<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let result = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand Down
6 changes: 2 additions & 4 deletions core/src/avm2/globals/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ impl<'gc> AvmSerializer<'gc> {
// If the user supplied a PropList, we use that to find properties on the object.
if let Some(Replacer::PropList(props)) = self.replacer {
let mut iter = ArrayIter::new(activation, props.into())?;
while let Some(r) = iter.next(activation) {
let item = r?.1;
while let Some((_, item)) = iter.next(activation)? {
let key = item.coerce_to_string(activation)?;
let value = Value::from(obj).get_public_property(key, activation)?;
let mapped = self.map_value(activation, || key, value)?;
Expand Down Expand Up @@ -202,8 +201,7 @@ impl<'gc> AvmSerializer<'gc> {
) -> Result<JsonValue, Error<'gc>> {
let mut js_arr = Vec::new();
let mut iter = ArrayIter::new(activation, iterable)?;
while let Some(r) = iter.next(activation) {
let (i, item) = r?;
while let Some((i, item)) = iter.next(activation)? {
let mc = activation.gc();
let mapped =
self.map_value(activation, || AvmString::new_utf8(mc, i.to_string()), item)?;
Expand Down
31 changes: 8 additions & 23 deletions core/src/avm2/globals/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ fn class_call<'gc>(

let mut iter = ArrayIter::new(activation, arg)?;

while let Some(r) = iter.next(activation) {
let (_, item) = r?;
while let Some((_, item)) = iter.next(activation)? {
let coerced_item = item.coerce_to_type(activation, value_type_for_coercion)?;
new_storage.push(coerced_item, activation)?;
}
Expand Down Expand Up @@ -398,9 +397,7 @@ pub fn every<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let result = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand All @@ -425,9 +422,7 @@ pub fn some<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let result = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand Down Expand Up @@ -458,9 +453,7 @@ pub fn filter<'gc>(
let mut new_storage = VectorStorage::new(0, false, value_type, activation);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let result = callback
.call(activation, receiver, &[item, i.into(), this.into()])?
.coerce_to_boolean();
Expand All @@ -485,9 +478,7 @@ pub fn for_each<'gc>(
let receiver = args.get(1).cloned().unwrap_or(Value::Null);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
callback.call(activation, receiver, &[item, i.into(), this.into()])?;
}

Expand Down Expand Up @@ -519,9 +510,7 @@ pub fn index_of<'gc>(

let mut iter = ArrayIter::with_bounds(activation, this, from_index, u32::MAX)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
if item == search_for {
return Ok(i.into());
}
Expand Down Expand Up @@ -555,9 +544,7 @@ pub fn last_index_of<'gc>(

let mut iter = ArrayIter::with_bounds(activation, this, 0, from_index)?;

while let Some(r) = iter.next_back(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next_back(activation)? {
if item == search_for {
return Ok(i.into());
}
Expand Down Expand Up @@ -585,9 +572,7 @@ pub fn map<'gc>(
let value_type_for_coercion = new_storage.value_type_for_coercion(activation);
let mut iter = ArrayIter::new(activation, this)?;

while let Some(r) = iter.next(activation) {
let (i, item) = r?;

while let Some((i, item)) = iter.next(activation)? {
let new_item = callback.call(activation, receiver, &[item, i.into(), this.into()])?;
let coerced_item = new_item.coerce_to_type(activation, value_type_for_coercion)?;

Expand Down

0 comments on commit 691a35f

Please sign in to comment.