From afdd617d29997911a1cbcf5ae6d1fc85d0b17b8d Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 5 Jun 2023 12:13:14 +0200 Subject: [PATCH] avm1: Add include_hidden: bool to get_keys() --- core/src/avm1/activation.rs | 10 +++++----- core/src/avm1/debug.rs | 4 ++-- core/src/avm1/globals/load_vars.rs | 4 ++-- core/src/avm1/globals/shared_object.rs | 4 ++-- core/src/avm1/object.rs | 9 +++++++-- core/src/avm1/object/script_object.rs | 12 ++++++++---- core/src/avm1/object/stage_object.rs | 8 ++++++-- core/src/avm1/object/super_object.rs | 6 +++++- core/src/display_object/movie_clip.rs | 8 ++++++-- core/src/external.rs | 2 +- 10 files changed, 44 insertions(+), 23 deletions(-) diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index d761a9bed..c4e84855f 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -1022,12 +1022,12 @@ impl<'a, 'gc> Activation<'a, 'gc> { match object { Value::MovieClip(_) => { let ob = object.coerce_to_object(self); - for k in ob.get_keys(self).into_iter().rev() { + for k in ob.get_keys(self, false).into_iter().rev() { self.stack_push(k.into()); } } Value::Object(ob) => { - for k in ob.get_keys(self).into_iter().rev() { + for k in ob.get_keys(self, false).into_iter().rev() { self.stack_push(k.into()); } } @@ -1044,11 +1044,11 @@ impl<'a, 'gc> Activation<'a, 'gc> { if let Value::MovieClip(_) = value { let object = value.coerce_to_object(self); - for k in object.get_keys(self).into_iter().rev() { + for k in object.get_keys(self, false).into_iter().rev() { self.stack_push(k.into()); } } else if let Value::Object(object) = value { - for k in object.get_keys(self).into_iter().rev() { + for k in object.get_keys(self, false).into_iter().rev() { self.stack_push(k.into()); } } else { @@ -2445,7 +2445,7 @@ impl<'a, 'gc> Activation<'a, 'gc> { /// WARNING: This does not support user defined virtual properties! pub fn object_into_form_values(&mut self, object: Object<'gc>) -> IndexMap { let mut form_values = IndexMap::new(); - let keys = object.get_keys(self); + let keys = object.get_keys(self, false); for k in keys { let v = object.get(k, self); diff --git a/core/src/avm1/debug.rs b/core/src/avm1/debug.rs index 220e3478a..c1cde3cf7 100644 --- a/core/src/avm1/debug.rs +++ b/core/src/avm1/debug.rs @@ -119,7 +119,7 @@ impl<'a> VariableDumper<'a> { object: &Object<'gc>, activation: &mut Activation<'_, 'gc>, ) { - let keys = object.get_keys(activation); + let keys = object.get_keys(activation, false); if keys.is_empty() { self.output.push_str(" {}"); } else { @@ -166,7 +166,7 @@ impl<'a> VariableDumper<'a> { object: &Object<'gc>, activation: &mut Activation<'_, 'gc>, ) { - let keys = object.get_keys(activation); + let keys = object.get_keys(activation, false); if keys.is_empty() { return; } diff --git a/core/src/avm1/globals/load_vars.rs b/core/src/avm1/globals/load_vars.rs index c09896f8e..21a916b98 100644 --- a/core/src/avm1/globals/load_vars.rs +++ b/core/src/avm1/globals/load_vars.rs @@ -171,7 +171,7 @@ fn send<'gc>( use indexmap::IndexMap; let mut form_values = IndexMap::new(); - let keys = this.get_keys(activation); + let keys = this.get_keys(activation, false); for k in keys { let v = this.get(k, activation); @@ -226,7 +226,7 @@ fn to_string<'gc>( use indexmap::IndexMap; let mut form_values = IndexMap::new(); - let keys = this.get_keys(activation); + let keys = this.get_keys(activation, false); for k in keys { let v = this.get(k, activation); diff --git a/core/src/avm1/globals/shared_object.rs b/core/src/avm1/globals/shared_object.rs index b2ef7609a..d9481fae0 100644 --- a/core/src/avm1/globals/shared_object.rs +++ b/core/src/avm1/globals/shared_object.rs @@ -102,7 +102,7 @@ fn recursive_serialize<'gc>( elements: &mut Vec, ) { // Reversed to match flash player ordering - for element_name in obj.get_keys(activation).into_iter().rev() { + for element_name in obj.get_keys(activation, false).into_iter().rev() { if let Ok(elem) = obj.get(element_name, activation) { if let Some(v) = serialize_value(activation, elem) { elements.push(Element::new(element_name.to_utf8_lossy(), v)); @@ -439,7 +439,7 @@ pub fn clear<'gc>( ) -> Result, Error<'gc>> { let data = this.get("data", activation)?.coerce_to_object(activation); - for k in &data.get_keys(activation) { + for k in &data.get_keys(activation, false) { data.delete(activation, *k); } diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index e4fe70040..f38549a28 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -477,8 +477,13 @@ pub trait TObject<'gc>: 'gc + Collect + Into> + Clone + Copy { } /// Enumerate the object. - fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec> { - self.raw_script_object().get_keys(activation) + fn get_keys( + &self, + activation: &mut Activation<'_, 'gc>, + include_hidden: bool, + ) -> Vec> { + self.raw_script_object() + .get_keys(activation, include_hidden) } /// Enumerate all interfaces implemented by this object. diff --git a/core/src/avm1/object/script_object.rs b/core/src/avm1/object/script_object.rs index f2218e94a..6d6e18833 100644 --- a/core/src/avm1/object/script_object.rs +++ b/core/src/avm1/object/script_object.rs @@ -444,9 +444,13 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> { } /// Enumerate the object. - fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec> { + fn get_keys( + &self, + activation: &mut Activation<'_, 'gc>, + include_hidden: bool, + ) -> Vec> { let proto_keys = if let Value::Object(proto) = self.proto(activation) { - proto.get_keys(activation) + proto.get_keys(activation, include_hidden) } else { Vec::new() }; @@ -461,7 +465,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> { // Then our own keys. out_keys.extend(self.0.read().properties.iter().filter_map(move |(k, p)| { - if p.is_enumerable() { + if include_hidden || p.is_enumerable() { Some(k) } else { None @@ -756,7 +760,7 @@ mod tests { Attribute::DONT_ENUM, ); - let keys: Vec<_> = object.get_keys(activation); + let keys: Vec<_> = object.get_keys(activation, false); assert_eq!(keys.len(), 2); assert!(keys.contains(&"stored".into())); assert!(!keys.contains(&"stored_hidden".into())); diff --git a/core/src/avm1/object/stage_object.rs b/core/src/avm1/object/stage_object.rs index 11fc3d010..638428623 100644 --- a/core/src/avm1/object/stage_object.rs +++ b/core/src/avm1/object/stage_object.rs @@ -330,11 +330,15 @@ impl<'gc> TObject<'gc> for StageObject<'gc> { false } - fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec> { + fn get_keys( + &self, + activation: &mut Activation<'_, 'gc>, + include_hidden: bool, + ) -> Vec> { // Keys from the underlying object are listed first, followed by // child display objects in order from highest depth to lowest depth. let obj = self.0.read(); - let mut keys = obj.base.get_keys(activation); + let mut keys = obj.base.get_keys(activation, include_hidden); if let Some(ctr) = obj.display_object.as_container() { // Button/MovieClip children are included in key list. diff --git a/core/src/avm1/object/super_object.rs b/core/src/avm1/object/super_object.rs index a76348afd..bcb7593d5 100644 --- a/core/src/avm1/object/super_object.rs +++ b/core/src/avm1/object/super_object.rs @@ -223,7 +223,11 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> { false } - fn get_keys(&self, _activation: &mut Activation<'_, 'gc>) -> Vec> { + fn get_keys( + &self, + _activation: &mut Activation<'_, 'gc>, + _include_hidden: bool, + ) -> Vec> { vec![] } diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 6469d88ad..8d4d000d0 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -1980,7 +1980,11 @@ impl<'gc> MovieClip<'gc> { if let Some(init_object) = init_object { // AVM1 sets keys in reverse order (compared to enumeration order). // This behavior is visible to setters, and some SWFs depend on it. - for key in init_object.get_keys(&mut activation).into_iter().rev() { + for key in init_object + .get_keys(&mut activation, false) + .into_iter() + .rev() + { if let Ok(value) = init_object.get(key, &mut activation) { let _ = object.set(key, value, &mut activation); } @@ -2011,7 +2015,7 @@ impl<'gc> MovieClip<'gc> { self.into(), ); - for key in init_object.get_keys(&mut activation) { + for key in init_object.get_keys(&mut activation, false) { if let Ok(value) = init_object.get(key, &mut activation) { let _ = object.set(key, value, &mut activation); } diff --git a/core/src/external.rs b/core/src/external.rs index 97f10452b..2b2cd8394 100644 --- a/core/src/external.rs +++ b/core/src/external.rs @@ -141,7 +141,7 @@ impl Value { .collect(); Value::List(values?) } else { - let keys = object.get_keys(activation); + let keys = object.get_keys(activation, false); let mut values = BTreeMap::new(); for key in keys { let value = object.get(key, activation)?;