avm1: Match Flash's property enumeration order (fix #153)
This commit is contained in:
parent
2cdf780e6f
commit
8da9487c0a
|
@ -1522,7 +1522,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
|
|
||||||
match object {
|
match object {
|
||||||
Value::Object(ob) => {
|
Value::Object(ob) => {
|
||||||
for k in ob.get_keys(self) {
|
for k in ob.get_keys(self).into_iter().rev() {
|
||||||
self.push(k);
|
self.push(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1539,7 +1539,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
let object = self.pop().as_object()?;
|
let object = self.pop().as_object()?;
|
||||||
|
|
||||||
self.push(Value::Null); // Sentinel that indicates end of enumeration
|
self.push(Value::Null); // Sentinel that indicates end of enumeration
|
||||||
for k in object.get_keys(self) {
|
for k in object.get_keys(self).into_iter().rev() {
|
||||||
self.push(k);
|
self.push(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,20 +463,23 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
let proto_keys = self.proto().map_or_else(Vec::new, |p| p.get_keys(avm));
|
let proto_keys = self.proto().map_or_else(Vec::new, |p| p.get_keys(avm));
|
||||||
let mut out_keys = vec![];
|
let mut out_keys = vec![];
|
||||||
let object = self.0.read();
|
let object = self.0.read();
|
||||||
for key in proto_keys {
|
|
||||||
if !object.values.contains_key(&key, avm.is_case_sensitive()) {
|
// Prototype keys come first.
|
||||||
out_keys.push(key);
|
out_keys.extend(
|
||||||
}
|
proto_keys
|
||||||
}
|
.into_iter()
|
||||||
for key in self.0.read().values.iter().filter_map(move |(k, p)| {
|
.filter(|k| !object.values.contains_key(k, avm.is_case_sensitive())),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then our own keys.
|
||||||
|
out_keys.extend(self.0.read().values.iter().filter_map(move |(k, p)| {
|
||||||
if p.is_enumerable() {
|
if p.is_enumerable() {
|
||||||
Some(k.to_string())
|
Some(k.to_string())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}));
|
||||||
out_keys.push(key)
|
|
||||||
}
|
|
||||||
out_keys
|
out_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,14 +255,11 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
|
||||||
// Keys from the underlying object are listed first, followed by
|
// Keys from the underlying object are listed first, followed by
|
||||||
// child display objects in order from highest depth to lowest depth.
|
// child display objects in order from highest depth to lowest depth.
|
||||||
let mut keys = self.base.get_keys(avm);
|
let mut keys = self.base.get_keys(avm);
|
||||||
for child in self
|
keys.extend(
|
||||||
.display_object
|
self.display_object
|
||||||
.children()
|
.children()
|
||||||
.map(|child| child.name().to_string())
|
.map(|child| child.name().to_string()),
|
||||||
{
|
);
|
||||||
keys.push(child)
|
|
||||||
}
|
|
||||||
|
|
||||||
keys
|
keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,12 +81,14 @@ impl<V> PropertyMap<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the value tuples in Flash's iteration order (most recently added first).
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&String, &V)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&String, &V)> {
|
||||||
self.0.iter().map(|(k, v)| (&k.0, v))
|
self.0.iter().rev().map(|(k, v)| (&k.0, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the key-value tuples in Flash's iteration order (most recently added first).
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&String, &mut V)> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&String, &mut V)> {
|
||||||
self.0.iter_mut().map(|(k, v)| (&k.0, v))
|
self.0.iter_mut().rev().map(|(k, v)| (&k.0, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&mut self, key: &str, case_sensitive: bool) -> Option<V> {
|
pub fn remove(&mut self, key: &str, case_sensitive: bool) -> Option<V> {
|
||||||
|
|
Loading…
Reference in New Issue