From a35402a0958398ed0fd2dd7995826d57987432cf Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:34:27 +0200 Subject: [PATCH 01/15] tests: Update avm1/tab_ordering_tabbable Add a case of a dynamic text field with tab enabled. --- .../avm1/tab_ordering_tabbable/input.json | 6 ++++++ .../avm1/tab_ordering_tabbable/output.txt | 3 +++ .../swfs/avm1/tab_ordering_tabbable/test.as | 5 ++++- .../swfs/avm1/tab_ordering_tabbable/test.swf | Bin 12261 -> 12294 bytes 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/tests/swfs/avm1/tab_ordering_tabbable/input.json b/tests/tests/swfs/avm1/tab_ordering_tabbable/input.json index 15b865ca2e94..30955fa002ee 100644 --- a/tests/tests/swfs/avm1/tab_ordering_tabbable/input.json +++ b/tests/tests/swfs/avm1/tab_ordering_tabbable/input.json @@ -11,6 +11,8 @@ { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 27 }, { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, @@ -24,6 +26,8 @@ { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 27 }, { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, @@ -37,5 +41,7 @@ { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, { "type": "KeyDown", "key_code": 27 } ] diff --git a/tests/tests/swfs/avm1/tab_ordering_tabbable/output.txt b/tests/tests/swfs/avm1/tab_ordering_tabbable/output.txt index 339952d7d10f..5204c5e91cfa 100644 --- a/tests/tests/swfs/avm1/tab_ordering_tabbable/output.txt +++ b/tests/tests/swfs/avm1/tab_ordering_tabbable/output.txt @@ -1,4 +1,5 @@ Tabbable elements: + _level0.text12: false _level0.button11: false _level0.button10: true _level0.clip9.text: false @@ -14,6 +15,7 @@ Tabbable elements: _level0.text1: false Enabling tab Tabbable elements: + _level0.text12: false _level0.button11: false _level0.button10: true _level0.clip9.text: false @@ -29,6 +31,7 @@ Tabbable elements: _level0.text1: false Setting custom order Tabbable elements: + _level0.text12: false _level0.button11: false _level0.button10: true _level0.clip9.text: false diff --git a/tests/tests/swfs/avm1/tab_ordering_tabbable/test.as b/tests/tests/swfs/avm1/tab_ordering_tabbable/test.as index c4fda1ed7e18..0c16eb74c477 100644 --- a/tests/tests/swfs/avm1/tab_ordering_tabbable/test.as +++ b/tests/tests/swfs/avm1/tab_ordering_tabbable/test.as @@ -12,6 +12,8 @@ text3._visible = false; text6.selectable = false; clip9._visible = false; button11._visible = false; +text12.type = "dynamic"; +text12.tabEnabled = true; var objects = [ text1, @@ -26,7 +28,8 @@ var objects = [ clip9, clip9.text, button10, - button11 + button11, + text12 ]; var tabbedObjects = []; diff --git a/tests/tests/swfs/avm1/tab_ordering_tabbable/test.swf b/tests/tests/swfs/avm1/tab_ordering_tabbable/test.swf index 9248c4afdcf276ed9217ed7dafb27505ab3e0f45..3675eb3edb72197d2119c8487d966257d5a236b0 100644 GIT binary patch delta 9622 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 MNInDjUm{jWJj1xz&j0`b delta 9590 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 From 641f038af14e18f27540b7c327b05d03b99ecafd Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:34:52 +0200 Subject: [PATCH 02/15] tests: Update avm1/tab_ordering_properties Add a case of a non-editable text field. --- .../avm1/tab_ordering_properties/output.txt | 76 ++++++++++++++++++ .../swfs/avm1/tab_ordering_properties/test.as | 3 + .../avm1/tab_ordering_properties/test.swf | Bin 11887 -> 11941 bytes 3 files changed, 79 insertions(+) diff --git a/tests/tests/swfs/avm1/tab_ordering_properties/output.txt b/tests/tests/swfs/avm1/tab_ordering_properties/output.txt index fad8532031ac..dc7ba2c50f5f 100644 --- a/tests/tests/swfs/avm1/tab_ordering_properties/output.txt +++ b/tests/tests/swfs/avm1/tab_ordering_properties/output.txt @@ -74,6 +74,82 @@ enumerated tabEnabled enumerated tabIndex enumerated tabChildren +===== non-editable text ===== + default + tabEnabled = undefined + tabIndex = undefined + tabChildren = undefined + enumerated tabIndex + after set 1 + tabEnabled = true + tabIndex = 0 + tabChildren = true + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 2 + tabEnabled = false + tabIndex = 4 + tabChildren = false + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 3 + tabEnabled = undefined + tabIndex = undefined + tabChildren = undefined + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 4 + tabEnabled = -4 + tabIndex = 4294967292 + tabChildren = -4 + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 5 + tabEnabled = 2147483647 + tabIndex = 2147483647 + tabChildren = 2147483647 + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 6 + tabEnabled = 2147483648 + tabIndex = 2147483648 + tabChildren = 2147483648 + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 7 + tabEnabled = x + tabIndex = 0 + tabChildren = x + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 8 + tabEnabled = -2147483648 + tabIndex = 2147483648 + tabChildren = -2147483648 + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 9 + tabEnabled = [object Object] + tabIndex = 0 + tabChildren = [object Object] + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren + after set 10 + tabEnabled = 1.1 + tabIndex = 1 + tabChildren = 1.1 + enumerated tabEnabled + enumerated tabIndex + enumerated tabChildren ===== button ===== default tabEnabled = undefined diff --git a/tests/tests/swfs/avm1/tab_ordering_properties/test.as b/tests/tests/swfs/avm1/tab_ordering_properties/test.as index c5cc27f57cd3..99fb7bc6df67 100644 --- a/tests/tests/swfs/avm1/tab_ordering_properties/test.as +++ b/tests/tests/swfs/avm1/tab_ordering_properties/test.as @@ -96,6 +96,9 @@ function testProperties(obj) { trace('===== text ====='); testProperties(text); +trace('===== non-editable text ====='); +text2.type = "dynamic"; +testProperties(text2); trace('===== button ====='); testProperties(button); trace('===== movie clip ====='); diff --git a/tests/tests/swfs/avm1/tab_ordering_properties/test.swf b/tests/tests/swfs/avm1/tab_ordering_properties/test.swf index 0ca6be93745f964b261be664a69d45427ddee787..577a71be1c2460c5965c0c256b5563cf3878c0e3 100644 GIT binary patch delta 11112 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 delta 11081 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 P)Q=>jd;|DjUL-nnBfyf| From 0e579a9c4ad9c4de1c90a20ec4befc409cb159df Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 03/15] avm1: Move tab_index to InteractiveObject and make it i32 The i32/u32 discrepancy is only a data presentation issue, as the value is treated as i32 in every case. --- core/src/avm1/globals/button.rs | 33 +++++++++++++------------- core/src/avm1/globals/movie_clip.rs | 33 +++++++++++++------------- core/src/avm1/globals/text_field.rs | 30 +++++++++++++---------- core/src/display_object/avm1_button.rs | 20 ---------------- core/src/display_object/edit_text.rs | 22 ----------------- core/src/display_object/interactive.rs | 12 ++++++++-- core/src/display_object/movie_clip.rs | 24 ------------------- 7 files changed, 60 insertions(+), 114 deletions(-) diff --git a/core/src/avm1/globals/button.rs b/core/src/avm1/globals/button.rs index 18fbc9f200ef..5b81ab785709 100644 --- a/core/src/avm1/globals/button.rs +++ b/core/src/avm1/globals/button.rs @@ -9,7 +9,7 @@ use crate::avm1::ArrayObject; use crate::avm1::{globals, Object, ScriptObject, TObject, Value}; use crate::avm1_stub; use crate::context::GcContext; -use crate::display_object::{Avm1Button, TDisplayObject}; +use crate::display_object::{Avm1Button, TDisplayObject, TInteractiveObject}; use crate::string::AvmString; macro_rules! button_getter { @@ -180,8 +180,8 @@ fn tab_index<'gc>( this: Avm1Button<'gc>, _activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - if let Some(index) = this.tab_index_value() { - Ok(index.into()) + if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) { + Ok(Value::Number(index as f64)) } else { Ok(Value::Undefined) } @@ -192,19 +192,18 @@ fn set_tab_index<'gc>( activation: &mut Activation<'_, 'gc>, value: Value<'gc>, ) -> Result<(), Error<'gc>> { - match value { - Value::Undefined | Value::Null => { - this.set_tab_index_value(&mut activation.context, None); - } - Value::Bool(_) | Value::Number(_) => { - // FIXME This coercion is not perfect, as it wraps - // instead of falling back to MIN, as FP does - let i32_value = value.coerce_to_i32(activation)?; - this.set_tab_index_value(&mut activation.context, Some(i32_value)); - } - _ => { - this.set_tab_index_value(&mut activation.context, Some(i32::MIN)); - } - }; + if let Some(this) = this.as_interactive() { + let value = match value { + Value::Undefined | Value::Null => None, + Value::Bool(_) | Value::Number(_) => { + // FIXME This coercion is not perfect, as it wraps + // instead of falling back to MIN, as FP does + let i32_value = value.coerce_to_i32(activation)?; + Some(i32_value) + } + _ => Some(i32::MIN), + }; + this.set_tab_index(&mut activation.context, value); + } Ok(()) } diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index 797326726758..8dc349147199 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -9,7 +9,7 @@ use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::{self, ArrayObject, Object, ScriptObject, TObject, Value}; use crate::backend::navigator::NavigationMethod; use crate::context::{GcContext, UpdateContext}; -use crate::display_object::{Bitmap, EditText, MovieClip}; +use crate::display_object::{Bitmap, EditText, MovieClip, TInteractiveObject}; use crate::ecma_conversions::f64_to_wrapping_i32; use crate::prelude::*; use crate::string::AvmString; @@ -1828,8 +1828,8 @@ fn tab_index<'gc>( this: MovieClip<'gc>, _activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - if let Some(index) = this.tab_index_value() { - Ok(index.into()) + if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) { + Ok(Value::Number(index as f64)) } else { Ok(Value::Undefined) } @@ -1840,19 +1840,18 @@ fn set_tab_index<'gc>( activation: &mut Activation<'_, 'gc>, value: Value<'gc>, ) -> Result<(), Error<'gc>> { - match value { - Value::Undefined | Value::Null => { - this.set_tab_index_value(&mut activation.context, None); - } - Value::Bool(_) | Value::Number(_) => { - // FIXME This coercion is not perfect, as it wraps - // instead of falling back to MIN, as FP does - let i32_value = value.coerce_to_i32(activation)?; - this.set_tab_index_value(&mut activation.context, Some(i32_value)); - } - _ => { - this.set_tab_index_value(&mut activation.context, Some(i32::MIN)); - } - }; + if let Some(this) = this.as_interactive() { + let value = match value { + Value::Undefined | Value::Null => None, + Value::Bool(_) | Value::Number(_) => { + // FIXME This coercion is not perfect, as it wraps + // instead of falling back to MIN, as FP does + let i32_value = value.coerce_to_i32(activation)?; + Some(i32_value) + } + _ => Some(i32::MIN), + }; + this.set_tab_index(&mut activation.context, value); + } Ok(()) } diff --git a/core/src/avm1/globals/text_field.rs b/core/src/avm1/globals/text_field.rs index d93d0cae253e..e7d3eb44a4d2 100644 --- a/core/src/avm1/globals/text_field.rs +++ b/core/src/avm1/globals/text_field.rs @@ -5,7 +5,9 @@ use crate::avm1::object::NativeObject; use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::{globals, ArrayObject, Object, ScriptObject, TObject, Value}; use crate::context::GcContext; -use crate::display_object::{AutoSizeMode, EditText, TDisplayObject, TextSelection}; +use crate::display_object::{ + AutoSizeMode, EditText, TDisplayObject, TInteractiveObject, TextSelection, +}; use crate::font::round_down_to_pixel; use crate::html::TextFormat; use crate::string::{AvmString, WStr}; @@ -919,8 +921,8 @@ pub fn tab_index<'gc>( this: EditText<'gc>, _activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - if let Some(index) = this.tab_index_value() { - Ok(index.into()) + if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) { + Ok(Value::Number(index as u32 as f64)) } else { Ok(Value::Undefined) } @@ -931,14 +933,18 @@ pub fn set_tab_index<'gc>( activation: &mut Activation<'_, 'gc>, value: Value<'gc>, ) -> Result<(), Error<'gc>> { - match value { - Value::Undefined | Value::Null => { - this.set_tab_index_value(&mut activation.context, None); - } - _ => { - let u32_value = value.coerce_to_u32(activation)?; - this.set_tab_index_value(&mut activation.context, Some(u32_value)); - } - }; + if let Some(this) = this.as_interactive() { + let value = match value { + Value::Undefined | Value::Null => None, + _ => { + // `tabIndex` is u32 in TextField, compared to i32 in Button and MovieClip, + // but that is only a data representation difference, + // as both are interpreted as i32. + let u32_value = value.coerce_to_u32(activation)?; + Some(u32_value as i32) + } + }; + this.set_tab_index(&mut activation.context, value); + } Ok(()) } diff --git a/core/src/display_object/avm1_button.rs b/core/src/display_object/avm1_button.rs index 654c8bb85786..d793c1e4bd86 100644 --- a/core/src/display_object/avm1_button.rs +++ b/core/src/display_object/avm1_button.rs @@ -46,9 +46,6 @@ pub struct Avm1ButtonData<'gc> { object: Lock>>, initialized: Cell, has_focus: Cell, - // TODO Consider moving this to InteractiveObject along with - // TextField's and MovieClip's tab indices after AVM2 analysis - tab_index: Cell>, } #[derive(Clone, Collect)] @@ -102,7 +99,6 @@ impl<'gc> Avm1Button<'gc> { ButtonTracking::Push }), has_focus: Cell::new(false), - tab_index: Cell::new(None), }, )) } @@ -245,18 +241,6 @@ impl<'gc> Avm1Button<'gc> { fn use_hand_cursor(self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_boolean_property(context, "useHandCursor", true) } - - /// Get the value of `tabIndex` used in AS. - /// - /// Do not confuse it with `tab_index`, which returns the value used for ordering. - pub fn tab_index_value(&self) -> Option { - self.0.tab_index.get() - } - - /// Set the value of `tabIndex` used in AS. - pub fn set_tab_index_value(&self, _context: &mut UpdateContext<'_, 'gc>, value: Option) { - self.0.tab_index.set(value) - } } impl<'gc> TDisplayObject<'gc> for Avm1Button<'gc> { @@ -637,10 +621,6 @@ impl<'gc> TInteractiveObject<'gc> for Avm1Button<'gc> { fn is_tabbable(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_avm1_boolean_property(context, "tabEnabled", |_| true) } - - fn tab_index(&self) -> Option { - self.0.tab_index.get().map(|i| i as i64) - } } impl<'gc> Avm1ButtonData<'gc> { diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index dcb378f6f6f7..b992fb5c2d40 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -180,11 +180,6 @@ pub struct EditTextData<'gc> { /// Restrict what characters the user may input. #[collect(require_static)] restrict: EditTextRestrict, - - // TODO Consider moving this to InteractiveObject along with - // MovieClip's and Button's tab indices after AVM2 analysis - // NOTE: `tabIndex` is u32 in TextField, compared to i32 in Button and MovieClip - tab_index: Option, } impl<'gc> EditTextData<'gc> { @@ -367,7 +362,6 @@ impl<'gc> EditText<'gc> { mouse_wheel_enabled: true, is_tlf: false, restrict: EditTextRestrict::allow_all(), - tab_index: None, }, )); @@ -2034,18 +2028,6 @@ impl<'gc> EditText<'gc> { .contains(Position::from((position.x, position.y))) }) } - - /// Get the value of `tabIndex` used in AS. - /// - /// Do not confuse it with `tab_index`, which returns the value used for ordering. - pub fn tab_index_value(&self) -> Option { - self.0.read().tab_index - } - - /// Set the value of `tabIndex` used in AS. - pub fn set_tab_index_value(&self, context: &mut UpdateContext<'_, 'gc>, value: Option) { - self.0.write(context.gc()).tab_index = value; - } } impl<'gc> TDisplayObject<'gc> for EditText<'gc> { @@ -2500,10 +2482,6 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> { } self.get_avm1_boolean_property(context, "tabEnabled", |_| true) } - - fn tab_index(&self) -> Option { - self.0.read().tab_index.map(|i| i as i64) - } } bitflags::bitflags! { diff --git a/core/src/display_object/interactive.rs b/core/src/display_object/interactive.rs index c0a2b6361a0b..4df18f0ae223 100644 --- a/core/src/display_object/interactive.rs +++ b/core/src/display_object/interactive.rs @@ -94,6 +94,9 @@ pub struct InteractiveObjectBase<'gc> { #[collect(require_static)] last_click: Option, + #[collect(require_static)] + tab_index: Option, + /// Specifies whether this object displays a yellow rectangle when focused. focus_rect: Option, } @@ -105,6 +108,7 @@ impl<'gc> Default for InteractiveObjectBase<'gc> { flags: InteractiveObjectFlags::MOUSE_ENABLED, context_menu: Avm2Value::Null, last_click: None, + tab_index: None, focus_rect: None, } } @@ -600,8 +604,12 @@ pub trait TInteractiveObject<'gc>: /// Used to customize tab ordering. /// When not `None`, a custom ordering is used, and /// objects are ordered according to this value. - fn tab_index(&self) -> Option { - None + fn tab_index(&self) -> Option { + self.raw_interactive().tab_index + } + + fn set_tab_index(&self, context: &mut UpdateContext<'_, 'gc>, value: Option) { + self.raw_interactive_mut(context.gc()).tab_index = value } } diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index c4fb23d9611a..b8bf42285d3a 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -189,10 +189,6 @@ pub struct MovieClipData<'gc> { /// Attached audio (AVM1) attached_audio: Option>, - - // TODO Consider moving this to InteractiveObject along with - // TextField's and Button's tab indices after AVM2 analysis - tab_index: Option, } impl<'gc> MovieClip<'gc> { @@ -230,7 +226,6 @@ impl<'gc> MovieClip<'gc> { tag_frame_boundaries: Default::default(), queued_tags: HashMap::new(), attached_audio: None, - tab_index: None, }, )) } @@ -274,7 +269,6 @@ impl<'gc> MovieClip<'gc> { tag_frame_boundaries: Default::default(), queued_tags: HashMap::new(), attached_audio: None, - tab_index: None, }, )) } @@ -319,7 +313,6 @@ impl<'gc> MovieClip<'gc> { tag_frame_boundaries: Default::default(), queued_tags: HashMap::new(), attached_audio: None, - tab_index: None, }, )) } @@ -389,7 +382,6 @@ impl<'gc> MovieClip<'gc> { tag_frame_boundaries: Default::default(), queued_tags: HashMap::new(), attached_audio: None, - tab_index: None, }, )); @@ -2562,18 +2554,6 @@ impl<'gc> MovieClip<'gc> { } } } - - /// Get the value of `tabIndex` used in AS. - /// - /// Do not confuse it with `tab_index`, which returns the value used for ordering. - pub fn tab_index_value(&self) -> Option { - self.0.read().tab_index - } - - /// Set the value of `tabIndex` used in AS. - pub fn set_tab_index_value(&self, context: &mut UpdateContext<'_, 'gc>, value: Option) { - self.0.write(context.gc()).tab_index = value; - } } impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> { @@ -3421,10 +3401,6 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { self.tab_index().is_some() || self.is_button_mode(context) }) } - - fn tab_index(&self) -> Option { - self.0.read().tab_index.map(|i| i as i64) - } } impl<'gc> MovieClipData<'gc> { From 011e858ae299028ba6164dd7aa1b0728caa7a625 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 12:08:18 +0200 Subject: [PATCH 04/15] tests: Add tab_ordering_custom_i32_vs_u32 test This test verifies the behavior of i32/u32 discrepancy in tabIndex in AVM1. --- .../tab_ordering_custom_i32_vs_u32/input.json | 7 +++++++ .../tab_ordering_custom_i32_vs_u32/output.txt | 12 ++++++++++++ .../tab_ordering_custom_i32_vs_u32/test.as | 18 ++++++++++++++++++ .../tab_ordering_custom_i32_vs_u32/test.swf | Bin 0 -> 11614 bytes .../tab_ordering_custom_i32_vs_u32/test.toml | 1 + 5 files changed, 38 insertions(+) create mode 100644 tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/input.json create mode 100644 tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/output.txt create mode 100644 tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.as create mode 100644 tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.swf create mode 100644 tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.toml diff --git a/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/input.json b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/input.json new file mode 100644 index 000000000000..581d6063cd89 --- /dev/null +++ b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/input.json @@ -0,0 +1,7 @@ +[ + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 } +] diff --git a/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/output.txt b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/output.txt new file mode 100644 index 000000000000..42fd5201413a --- /dev/null +++ b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/output.txt @@ -0,0 +1,12 @@ +Focus changed + old: null + new: _level0.text +Focus changed + old: _level0.text + new: _level0.text2 +Focus changed + old: _level0.text2 + new: _level0.button +Focus changed + old: _level0.button + new: _level0.text diff --git a/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.as b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.as new file mode 100644 index 000000000000..6ffe1bf2274f --- /dev/null +++ b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.as @@ -0,0 +1,18 @@ +var counter = 0; +var listener = new Object(); +listener.onSetFocus = function(oldFocus, newFocus) { + ++counter; + if (counter > 4) { + return; + } + if (newFocus) { + trace("Focus changed"); + trace(" old: " + oldFocus); + trace(" new: " + newFocus); + } +}; +Selection.addListener(listener); + +text.tabIndex = 4294967293; +text2.tabIndex = -2; +button.tabIndex = 0; diff --git a/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.swf b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..ebc7b4aeb6f0ad75f571561880f352540a687142 GIT binary patch literal 11614 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 c*^bQn`t95IHvWIMv8CLDq%i>h1Qc>n+a literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.toml b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.toml new file mode 100644 index 000000000000..cf6123969a1d --- /dev/null +++ b/tests/tests/swfs/avm1/tab_ordering_custom_i32_vs_u32/test.toml @@ -0,0 +1 @@ +num_ticks = 1 From c01d45f2606c91ed6754f4342db887b173dc0922 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:29:57 +0200 Subject: [PATCH 05/15] avm2: Call focus handler in AVM2 buttons The focus handler should also be called for AVM2 buttons when the focus is being changed. --- core/src/display_object/avm2_button.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index 47e34a86dbe5..a9f29dca27e0 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -826,11 +826,12 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { fn on_focus_changed( &self, - _context: &mut UpdateContext<'_, 'gc>, + context: &mut UpdateContext<'_, 'gc>, focused: bool, - _other: Option>, + other: Option>, ) { self.0.has_focus.set(focused); + self.call_focus_handler(context, focused, other); } } From e0df7ffe72d3fa4f7f758e67031308a578c93d2e Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 06/15] core: Allow setting tabEnabled for AVM2 The field tab_enabled in AVM1 is effectively read-only as tabEnabled is not a built-in property of objects. That is not the case in AVM2, where tab_enabled is native. This patch covers both of these cases by introducing methods: * tab_enabled, * set_tab_enabled, * tab_enabled_avm1, * tab_enabled_avm2_default. --- core/src/display_object/avm1_button.rs | 2 +- core/src/display_object/avm2_button.rs | 4 +++ core/src/display_object/edit_text.rs | 8 ++++++ core/src/display_object/interactive.rs | 39 +++++++++++++++++++++++++- core/src/display_object/movie_clip.rs | 6 +++- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/core/src/display_object/avm1_button.rs b/core/src/display_object/avm1_button.rs index d793c1e4bd86..095ed6a5e323 100644 --- a/core/src/display_object/avm1_button.rs +++ b/core/src/display_object/avm1_button.rs @@ -618,7 +618,7 @@ impl<'gc> TInteractiveObject<'gc> for Avm1Button<'gc> { self.call_focus_handler(context, focused, other); } - fn is_tabbable(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + fn tab_enabled_avm1(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_avm1_boolean_property(context, "tabEnabled", |_| true) } } diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index a9f29dca27e0..07c80bcc8249 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -833,6 +833,10 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { self.0.has_focus.set(focused); self.call_focus_handler(context, focused, other); } + + fn tab_enabled_avm2_default(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { + true + } } impl<'gc> Avm2ButtonData<'gc> { diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index b992fb5c2d40..3086dfb86260 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -2480,8 +2480,16 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> { // Non-editable text fields are never tabbable. return false; } + self.tab_enabled(context) + } + + fn tab_enabled_avm1(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_avm1_boolean_property(context, "tabEnabled", |_| true) } + + fn tab_enabled_avm2_default(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { + self.is_editable() + } } bitflags::bitflags! { diff --git a/core/src/display_object/interactive.rs b/core/src/display_object/interactive.rs index 4df18f0ae223..20a673952f54 100644 --- a/core/src/display_object/interactive.rs +++ b/core/src/display_object/interactive.rs @@ -94,6 +94,9 @@ pub struct InteractiveObjectBase<'gc> { #[collect(require_static)] last_click: Option, + #[collect(require_static)] + tab_enabled: Option, + #[collect(require_static)] tab_index: Option, @@ -108,6 +111,7 @@ impl<'gc> Default for InteractiveObjectBase<'gc> { flags: InteractiveObjectFlags::MOUSE_ENABLED, context_menu: Avm2Value::Null, last_click: None, + tab_enabled: None, tab_index: None, focus_rect: None, } @@ -597,10 +601,43 @@ pub trait TInteractiveObject<'gc>: } /// Whether this object is included in tab ordering. - fn is_tabbable(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { + fn is_tabbable(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + self.tab_enabled(context) + } + + /// Sets whether tab ordering is enabled for this object. + /// + /// Some objects may be excluded from tab ordering + /// even if it's enabled, see [`Self::is_tabbable()`]. + fn tab_enabled(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + if context.swf.is_action_script_3() { + self.raw_interactive() + .tab_enabled + .unwrap_or_else(|| self.tab_enabled_avm2_default(context)) + } else { + self.tab_enabled_avm1(context) + } + } + + /// Look up the `tabEnabled` property from AVM1. + /// + /// Do not use this directly, use [`Self::is_tabbable()`] or [`Self::tab_enabled()`]. + fn tab_enabled_avm1(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { + false + } + + fn tab_enabled_avm2_default(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { false } + fn set_tab_enabled(&self, context: &mut UpdateContext<'_, 'gc>, value: bool) { + if context.swf.is_action_script_3() { + self.raw_interactive_mut(context.gc()).tab_enabled = Some(value) + } else { + tracing::warn!("Trying to set tab_enabled on an AVM1 object, this has no effect") + } + } + /// Used to customize tab ordering. /// When not `None`, a custom ordering is used, and /// objects are ordered according to this value. diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index b8bf42285d3a..ba242f51ca64 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -3396,11 +3396,15 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { self.call_focus_handler(context, focused, other); } - fn is_tabbable(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + fn tab_enabled_avm1(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_avm1_boolean_property(context, "tabEnabled", |context| { self.tab_index().is_some() || self.is_button_mode(context) }) } + + fn tab_enabled_avm2_default(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + self.is_button_mode(context) + } } impl<'gc> MovieClipData<'gc> { From 07ec8dc039f02bbd5a72b859e1b287da73e402d1 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 07/15] avm2: Implement InteractiveObject.tabIndex --- core/src/avm2/error.rs | 17 +++++++++++ .../flash/display/interactive_object.rs | 28 +++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/core/src/avm2/error.rs b/core/src/avm2/error.rs index 7f5d99b4c81e..0f791bd45040 100644 --- a/core/src/avm2/error.rs +++ b/core/src/avm2/error.rs @@ -427,6 +427,23 @@ pub fn make_error_2008<'gc>(activation: &mut Activation<'_, 'gc>, param_name: &s } } +#[inline(never)] +#[cold] +pub fn make_error_2027<'gc>(activation: &mut Activation<'_, 'gc>, value: i32) -> Error<'gc> { + let err = range_error( + activation, + &format!( + "Error #2027: Parameter tabIndex must be a non-negative number; got {}.", + value + ), + 2027, + ); + match err { + Ok(err) => Error::AvmError(err), + Err(err) => err, + } +} + #[inline(never)] #[cold] pub fn make_error_2037<'gc>(activation: &mut Activation<'_, 'gc>) -> Error<'gc> { diff --git a/core/src/avm2/globals/flash/display/interactive_object.rs b/core/src/avm2/globals/flash/display/interactive_object.rs index 43d148fc2963..b22f9f67af64 100644 --- a/core/src/avm2/globals/flash/display/interactive_object.rs +++ b/core/src/avm2/globals/flash/display/interactive_object.rs @@ -1,6 +1,7 @@ //! `flash.display.InteractiveObject` builtin/prototype use crate::avm2::activation::Activation; +use crate::avm2::error::make_error_2027; use crate::avm2::object::{Object, TObject}; use crate::avm2::parameters::ParametersExt; use crate::avm2::value::Value; @@ -139,21 +140,32 @@ pub fn set_tab_enabled<'gc>( } pub fn get_tab_index<'gc>( - activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, + _activation: &mut Activation<'_, 'gc>, + this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_getter!(activation, "flash.display.InteractiveObject", "tabIndex"); - - Ok((-1).into()) + if let Some(obj) = this + .as_display_object() + .and_then(|this| this.as_interactive()) + { + Ok(Value::Number(obj.tab_index().unwrap_or(-1) as f64)) + } else { + Ok(Value::Undefined) + } } pub fn set_tab_index<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, - _args: &[Value<'gc>], + this: Object<'gc>, + args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_setter!(activation, "flash.display.InteractiveObject", "tabIndex"); + if let Some(obj) = this.as_display_object().and_then(|o| o.as_interactive()) { + let value = args.get_i32(activation, 0)?; + if value < 0 { + return Err(make_error_2027(activation, value)); + } + obj.set_tab_index(&mut activation.context, Some(value)); + } Ok(Value::Undefined) } From 1b5b1e696c29c6cdfe44962a621c52da5974d686 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 08/15] avm2: Implement InteractiveObject.tabEnabled --- .../flash/display/interactive_object.rs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/src/avm2/globals/flash/display/interactive_object.rs b/core/src/avm2/globals/flash/display/interactive_object.rs index b22f9f67af64..23cd6740d850 100644 --- a/core/src/avm2/globals/flash/display/interactive_object.rs +++ b/core/src/avm2/globals/flash/display/interactive_object.rs @@ -121,20 +121,28 @@ pub fn set_context_menu<'gc>( pub fn get_tab_enabled<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, + this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_getter!(activation, "flash.display.InteractiveObject", "tabEnabled"); - - Ok(false.into()) + if let Some(obj) = this.as_display_object().and_then(|o| o.as_interactive()) { + Ok(Value::Bool(obj.tab_enabled(&mut activation.context))) + } else { + Ok(Value::Undefined) + } } pub fn set_tab_enabled<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, - _args: &[Value<'gc>], + this: Object<'gc>, + args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_setter!(activation, "flash.display.InteractiveObject", "tabIndex"); + if let Some(obj) = this + .as_display_object() + .and_then(|this| this.as_interactive()) + { + let value = args.get_bool(0); + obj.set_tab_enabled(&mut activation.context, value); + } Ok(Value::Undefined) } From 7c68adfb5b0432d5dfa5946ff5a7a3c6ac4463a2 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:32:16 +0200 Subject: [PATCH 09/15] tests: Add avm2/tab_ordering_tabbable This is an AVM2 version of avm1/tab_ordering_tabbable --- .../swfs/avm2/tab_ordering_tabbable/Test.as | 144 ++++++++++++++++++ .../avm2/tab_ordering_tabbable/input.json | 47 ++++++ .../avm2/tab_ordering_tabbable/output.txt | 47 ++++++ .../swfs/avm2/tab_ordering_tabbable/test.swf | Bin 0 -> 2323 bytes .../swfs/avm2/tab_ordering_tabbable/test.toml | 1 + 5 files changed, 239 insertions(+) create mode 100644 tests/tests/swfs/avm2/tab_ordering_tabbable/Test.as create mode 100644 tests/tests/swfs/avm2/tab_ordering_tabbable/input.json create mode 100644 tests/tests/swfs/avm2/tab_ordering_tabbable/output.txt create mode 100644 tests/tests/swfs/avm2/tab_ordering_tabbable/test.swf create mode 100644 tests/tests/swfs/avm2/tab_ordering_tabbable/test.toml diff --git a/tests/tests/swfs/avm2/tab_ordering_tabbable/Test.as b/tests/tests/swfs/avm2/tab_ordering_tabbable/Test.as new file mode 100644 index 000000000000..a70b8fb05674 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_tabbable/Test.as @@ -0,0 +1,144 @@ +package { + +import flash.display.DisplayObject; +import flash.display.InteractiveObject; +import flash.events.KeyboardEvent; +import flash.text.TextField; +import flash.display.Sprite; +import flash.display.SimpleButton; +import flash.display.MovieClip; +import flash.events.Event; + +public class Test extends MovieClip { + var objects:Array; + var tabbedObjects:Array = []; + var testStage:int = 0; + + public function Test() { + super(); + + var text1:TextField = this.newTextField(1); + text1.type = "dynamic"; + + var text2:TextField = this.newTextField(2); + text2.maxChars = 0; + + var text3:TextField = this.newTextField(3); + text3.visible = false; + + var text4:TextField = this.newTextField(4); + text4.x = -400; + text4.y = -400; + + var text5:TextField = this.newTextField(5); + + var text6:TextField = this.newTextField(6); + text6.selectable = false; + + var text7:TextField = this.newTextField(7); + text7.width = 0; + text7.height = 0; + + var clip8:MovieClip = this.newMovieClip(8); + + var clip9:MovieClip = this.newMovieClip(9); + clip9.visible = false; + + var button10:SimpleButton = new SimpleButton(); + button10.name = "button10"; + setupObject(button10, 10); + + var button11:SimpleButton = new SimpleButton(); + button11.name = "button11"; + setupObject(button11, 11); + button11.visible = false; + + var text12:TextField = this.newTextField(12); + text12.tabEnabled = true; + text12.type = "dynamic"; + + this.objects = [ + text1, + text2, + text3, + text4, + text5, + text6, + text7, + clip8, + clip8.getChildByName("clip8.text"), + clip9, + clip9.getChildByName("clip9.text"), + button10, + button11, + text12 + ]; + + var test:Test = this; + for each (var obj in objects) { + obj.addEventListener("focusIn", function(obj) { + return function (evt:Event):void { + test.tabbedObjects.push(obj.name); + } + }(obj)); + this.stage.addChild(obj); + } + + this.stage.addEventListener("keyDown", function(evt:KeyboardEvent) { + if (evt.keyCode == 27) { + trace("Tabbable elements:"); + for each (var obj in objects) { + var exists = false; + for each (var name in tabbedObjects) { + if (obj.name == name) { + exists = true; + } + } + trace(" " + obj.name + ": " + exists); + } + + ++test.testStage; + if (test.testStage == 1) { + trace("Enabling tab"); + for each (var obj in objects) { + obj.tabEnabled = true; + } + } else if (test.testStage == 2) { + trace("Setting custom order"); + for (var i in objects) { + objects[i].tabIndex = i; + } + } + } + }); + } + + function newTextField(i:int):TextField { + var tf:TextField = new TextField(); + tf.type = "input"; + tf.name = "text" + i; + tf.border = true; + this.setupObject(tf, i); + return tf; + } + + function newMovieClip(i:int):MovieClip { + var mc:MovieClip = new MovieClip(); + mc.name = "clip" + i; + this.setupObject(mc, i); + + var tf:TextField = this.newTextField(0); + tf.name = mc.name + ".text"; + + mc.addChild(tf); + return mc; + } + + function setupObject(o:DisplayObject, i:int):void { + o.x = 0; + o.y = i * 20; + o.height = 20; + o.width = 100; + } +} +} diff --git a/tests/tests/swfs/avm2/tab_ordering_tabbable/input.json b/tests/tests/swfs/avm2/tab_ordering_tabbable/input.json new file mode 100644 index 000000000000..30955fa002ee --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_tabbable/input.json @@ -0,0 +1,47 @@ +[ + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 } +] diff --git a/tests/tests/swfs/avm2/tab_ordering_tabbable/output.txt b/tests/tests/swfs/avm2/tab_ordering_tabbable/output.txt new file mode 100644 index 000000000000..a4c0425f1980 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_tabbable/output.txt @@ -0,0 +1,47 @@ +Tabbable elements: + text1: false + text2: true + text3: false + text4: true + text5: true + text6: true + text7: true + clip8: false + clip8.text: true + clip9: false + clip9.text: false + button10: true + button11: false + text12: false +Enabling tab +Tabbable elements: + text1: false + text2: true + text3: false + text4: true + text5: true + text6: true + text7: true + clip8: true + clip8.text: true + clip9: false + clip9.text: false + button10: true + button11: false + text12: false +Setting custom order +Tabbable elements: + text1: false + text2: true + text3: false + text4: true + text5: true + text6: true + text7: true + clip8: true + clip8.text: true + clip9: false + clip9.text: true + button10: true + button11: false + text12: false diff --git a/tests/tests/swfs/avm2/tab_ordering_tabbable/test.swf b/tests/tests/swfs/avm2/tab_ordering_tabbable/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..d025eeeaa315d20c06b8caa7c89ecd10ea156b83 GIT binary patch literal 2323 zcmV+u3GDVmS5qmY4FCXm0fkmea~sDIo|&E9!Qw>_qDYAZCD4LJO9qLj_>x4CA_cu4 z7G>*UL(Bp@ORNQ8VPL^WC1ul0s_dkkN0k#NM^z5_8%YkSN^THck#4S3PEK;rl+ z*q!;MrTe$rp zxo^18j7{2Tw<>hivCZIqnCig-M%}4z)SPxJkzr5x#)4yV)dj~qdJnQ>l&U=b>VnKL zNR>>P#@FqZ+amEenThK%rAsa}OYl-1@OFJA4hi`Px0c?iOrbHT~VdU0CaTN@i|A+3YfPHyYem zGu9U>Mzh6M?UoHu<8{2@Z$ao~a8u>#nr*rjt-|e{i= zwN$&_XuHt*>#kPvQs3)s@6WJe*IiO8Q%R+I@$O;vGJ>6mXSXi}p#yEG&NrLJ#=!FO zinHuG%O zE<*nSpL_R5>)y54EAM4^^1c&7J~O3cr>1&UJU~>vpZNSo@E{%x3Xb}KM)L^Wkh8}V}$8G%+y{+qb%IVXg{L^j2vZTSU--3u>J;S;S-Ev zM&4vSql}(n^faSyGn!;{jL~sMQ;en=$*@R{Me>aL7@1)7IHS}0In3yJMrRp4$H*Kb z^Nd_%WPy=IMlLZ@VB|6*R~R|N$Rs0I8NJ2m9TvII=mSO#7A~k{Yoc& z8MK51gRz%bL681T#rs8UVT%+MOR;D{#izsvfFVQ)hK|AZ!~3V7r(fd3_#sEnYWO8) z=pm>d&EYEu7~pV<;tvG=NkD0gY&{>@dNHz9rZ80L!4RcqmM<~XcL^h~#il41_2iL) z4t~r8Dr-f*<==v&83^emR?<#vJ%5P@34e)wiY55y)(c?)&Q~NB*(&Q1_`jl;^pfuc zI1ww`7A?^}IH{-}bD$EW*z;t4n!0>IN`?CIA}yB@Pl>-`G$nNJgSdGOO^ z%?kXX431082zYwOOGqGr`z|0a=8r@JsE&CIAMKAh{5odQ+&*ap#YfV?Ke`SgcOfiy zmyGl+O0qaz6>T6J@yJ&9lMU>W9fQn?HJO%@YK2Ow5f-bG^>4dje;=wtduSl^M+zzL z?WFIY{wowHfqFTPZ$@e%jz_j?VG-`UhblxwJ6DnDiB94HbB#_Z32Blu<>J>2rdS%o&EQY0;cGXlI12uh9{AXvU$LJTw_pJuRh(xMg zq$*CxmDXKpA^}Kk)HoteN;T`MnHU8%1Mf%0Tf4JCaatmLg(18dtNBDmuJrCo7n6X} zWmMA~7l*G6qs`%(U(A5kpFCq66K6Yen(!BnlT+gSYfM1Q!bTuD3788K6G#L+%$%G{ z!i&;Rup3uUEPy(A(uj*iIq}j~=!na(z~Tx>BCdi|#5IsqTnDL&8z41t6C@M2K>EaO zDU(x$5iIV&R2T0^nVgY|yD;^OC6EDe4`lGYaK$g~Llm-{;z0sE@4zK_5lKOdaQyZ5 z30dEVfD9+k&Jh#ZpePsfxbOy?^>N37gjd6b1l+L)S%vie8Cpm25n;ei^1_@_c$1t0 zqaR#G;gbkQ(I_HO^cGU0=oF$+bQ-Bq^fuC>D2Z4UjUitQ{?q9(ltTVtltzJJltIBL z-2G4lDF|+XD&K&MK>2Y8S}~43eu=N+PsAt1=(Q-?j6N5ecsqFm8tzm0-hB2HQon`a z!eqq{acBFPm;N8&?JMw4Q=$IAV_^CWcd0&uC+8jfImqke3oJgz#n`nN+KfFHKL)P5 z9@kIyNWOr|A+K^T#7`kp*0JQ0^!9VS{k4~mUwB@ajCUHmeCc_47kvr*ar`9~zr@d= z2m8gZ@U!hi-*1fp@fB$Lj6v~h_?pn2zrk<;eFUD<3!OAj1UV{BSQF{uq&1l?=B<3X tIAu+xi__M0x;SIaq>C{t=7|SrxcjR_z|Ide`k}qQ&2tE${{o16|7U9Rl5GG0 literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/tab_ordering_tabbable/test.toml b/tests/tests/swfs/avm2/tab_ordering_tabbable/test.toml new file mode 100644 index 000000000000..cf6123969a1d --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_tabbable/test.toml @@ -0,0 +1 @@ +num_ticks = 1 From a9fecbf4de4b0ec17ccc8b57675e548f4757a003 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:32:40 +0200 Subject: [PATCH 10/15] tests: Add avm2/tab_ordering_custom_basic This is an AVM2 version of avm1/tab_ordering_custom_basic --- .../avm2/tab_ordering_custom_basic/Test.as | 70 ++++++++++++++++++ .../avm2/tab_ordering_custom_basic/input.json | 19 +++++ .../avm2/tab_ordering_custom_basic/output.txt | 34 +++++++++ .../avm2/tab_ordering_custom_basic/test.swf | Bin 0 -> 1566 bytes .../avm2/tab_ordering_custom_basic/test.toml | 1 + 5 files changed, 124 insertions(+) create mode 100644 tests/tests/swfs/avm2/tab_ordering_custom_basic/Test.as create mode 100644 tests/tests/swfs/avm2/tab_ordering_custom_basic/input.json create mode 100644 tests/tests/swfs/avm2/tab_ordering_custom_basic/output.txt create mode 100644 tests/tests/swfs/avm2/tab_ordering_custom_basic/test.swf create mode 100644 tests/tests/swfs/avm2/tab_ordering_custom_basic/test.toml diff --git a/tests/tests/swfs/avm2/tab_ordering_custom_basic/Test.as b/tests/tests/swfs/avm2/tab_ordering_custom_basic/Test.as new file mode 100644 index 000000000000..0d301750de71 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_custom_basic/Test.as @@ -0,0 +1,70 @@ +package { + +import flash.display.DisplayObject; +import flash.display.InteractiveObject; +import flash.events.KeyboardEvent; +import flash.text.TextField; +import flash.display.Sprite; +import flash.display.SimpleButton; +import flash.display.MovieClip; +import flash.events.Event; +import flash.events.FocusEvent; + +public class Test extends MovieClip { + var text1:TextField; + var text2:TextField; + var text3:TextField; + var text4:TextField; + var text5:TextField; + var text6:TextField; + + public function Test() { + super(); + + text1 = this.newTextField(1); + text2 = this.newTextField(2); + text3 = this.newTextField(3); + text4 = this.newTextField(4); + text5 = this.newTextField(5); + text6 = this.newTextField(6); + + text2.tabIndex = 2; + text3.tabIndex = 1; + text4.tabIndex = 4; + text4.tabEnabled = false; + text5.tabIndex = 3; + text6.tabIndex = 5; + + this.stage.focus = text1; + + var test:Test = this; + for each (var obj in [text1, text2, text3, text4, text5, text6]) { + obj.addEventListener("focusIn", function (evt:FocusEvent):void { + trace("Focus changed: " + evt.relatedObject.name + " -> " + evt.target.name); + }); + this.stage.addChild(obj); + } + + this.stage.addEventListener("keyDown", function(evt:KeyboardEvent) { + if (evt.keyCode == 27) { + trace("Escape pressed"); + test.stage.focus = test.text5; + } else if (evt.keyCode == 9) { + trace("Tab pressed"); + } + }); + } + + function newTextField(i:int):TextField { + var tf:TextField = new TextField(); + tf.type = "input"; + tf.name = "text" + i; + tf.border = true; + tf.x = 0; + tf.y = i * 20; + tf.height = 20; + tf.width = 100; + return tf; + } +} +} diff --git a/tests/tests/swfs/avm2/tab_ordering_custom_basic/input.json b/tests/tests/swfs/avm2/tab_ordering_custom_basic/input.json new file mode 100644 index 000000000000..7c7d8c3fbc71 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_custom_basic/input.json @@ -0,0 +1,19 @@ +[ + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 } +] diff --git a/tests/tests/swfs/avm2/tab_ordering_custom_basic/output.txt b/tests/tests/swfs/avm2/tab_ordering_custom_basic/output.txt new file mode 100644 index 000000000000..e0513b3aa9c1 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_custom_basic/output.txt @@ -0,0 +1,34 @@ +Tab pressed +Focus changed: text1 -> text3 +Tab pressed +Focus changed: text3 -> text2 +Tab pressed +Focus changed: text2 -> text5 +Tab pressed +Focus changed: text5 -> text6 +Tab pressed +Focus changed: text6 -> text3 +Tab pressed +Focus changed: text3 -> text2 +Tab pressed +Focus changed: text2 -> text5 +Tab pressed +Focus changed: text5 -> text6 +Escape pressed +Focus changed: text6 -> text5 +Tab pressed +Focus changed: text5 -> text6 +Tab pressed +Focus changed: text6 -> text3 +Tab pressed +Focus changed: text3 -> text2 +Tab pressed +Focus changed: text2 -> text5 +Tab pressed +Focus changed: text5 -> text6 +Tab pressed +Focus changed: text6 -> text3 +Tab pressed +Focus changed: text3 -> text2 +Tab pressed +Focus changed: text2 -> text5 diff --git a/tests/tests/swfs/avm2/tab_ordering_custom_basic/test.swf b/tests/tests/swfs/avm2/tab_ordering_custom_basic/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..54dff789563c8ff8cab274e7a16f7a597f50f91a GIT binary patch literal 1566 zcmV+(2I2WbS5qk{2><|i0fkjdbKA%fo*94~K17PNs23^Qlm+Xxe1N1R%alw@E1I_U z<-~HbsZ_C4Lt-FeO#v)$C{m}m_6HERHus$NW~BB9Xd9p`o7qE9 zHPb!a-`CSK-2eti{trUYzaX@LQ8m7Z5czt9SvbyxX*mjxa1U?FM8Gt0$hU zt=&Y`nzunaJ-h9N)S7wT=I7iL-FzWefIwQatXuXu6BX9!w2dZn!{rCrZp&)E>9Y%- z)!VGw+RuLkx*TDMHm@9ZShK~`wKgB54?og9@EGA@wU2pLZceEKBgZ_pmzT%*6zB3f zy++&Uwz&OapA$ycd!1FQruXex)l_S^%lQ*nf=w_$;r1bUscg?8d_lD zsm6Yk_R$f!zP|o_NCKB1h8%nIj}o*ALRZVb{^^gP{XO)WcLn-e;;-O$J>D{gaxUnl z?5!kzAtHIG;@+OS&atjf*sRH?YgV(@O*dO`NUoLB5u3LmbM0m0JKhws${s>L*`!E;UPJb!pn$`@62C*SB9ZDE-6UUTF$quXh-%ktOOg~5;7 zMkg_8Kk3+p;L4=2IwpQ*^bNl}vNRrj)@`y5Pj_tI?Q%^PaFM>QfY$H{J`meJ-M!23 zYu5MxiG0Z~8y2%QFOJ{6c}1NvdH*%wYX)y?9<$)hMQ<*7^OiU71O#gwn;IX4KzU}e zMw@HY+vV7dF>M_7E2AqoTuuNCM=hhRx%pPDzA0Ia?}F~0d3VAF5jreyHV%ys>n83q z%uY|p;ShmJ(JiwR!7B|jX!q+!6(TaPqKFwY-Ofi3YdS;yp>r~^qVH)li z;J9k0#yK2I@ zKh)z2VY5zpsNYdAD9b~AMv*~z0LmJhb5@3WSdqY>4E2QK17&rnhlYBLO*!iv58b4k z4F&xGCWr=cfCwBw|JMKgzhkQi1v&obXvIx?ljAnYtR3LmJlTK)W+9Yosx81>ZWJXF zzq-B-NCD!g;K^(rklLaL+pUGPh~0AzMpsJW&+NW)I8qWU?R-8`G`8# Date: Fri, 19 Apr 2024 00:33:11 +0200 Subject: [PATCH 11/15] tests: Add avm2/tab_ordering_automatic_basic This is an AVM2 version of avm1/tab_ordering_automatic_basic --- .../avm2/tab_ordering_automatic_basic/Test.as | 79 ++++++++++++++++++ .../tab_ordering_automatic_basic/input.json | 25 ++++++ .../tab_ordering_automatic_basic/output.txt | 45 ++++++++++ .../tab_ordering_automatic_basic/test.swf | Bin 0 -> 1613 bytes .../tab_ordering_automatic_basic/test.toml | 1 + 5 files changed, 150 insertions(+) create mode 100644 tests/tests/swfs/avm2/tab_ordering_automatic_basic/Test.as create mode 100644 tests/tests/swfs/avm2/tab_ordering_automatic_basic/input.json create mode 100644 tests/tests/swfs/avm2/tab_ordering_automatic_basic/output.txt create mode 100644 tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.swf create mode 100644 tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.toml diff --git a/tests/tests/swfs/avm2/tab_ordering_automatic_basic/Test.as b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/Test.as new file mode 100644 index 000000000000..200292577f7e --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/Test.as @@ -0,0 +1,79 @@ +package { + +import flash.display.DisplayObject; +import flash.display.InteractiveObject; +import flash.events.KeyboardEvent; +import flash.text.TextField; +import flash.display.Sprite; +import flash.display.SimpleButton; +import flash.display.MovieClip; +import flash.events.Event; +import flash.events.FocusEvent; + +public class Test extends MovieClip { + var text1:TextField; + var text2:TextField; + var text3:TextField; + var text4:TextField; + var testStage:int = 0; + + public function Test() { + super(); + + text1 = this.newTextField(1); + text2 = this.newTextField(2); + text3 = this.newTextField(3); + text4 = this.newTextField(4); + + this.stage.focus = text1; + + var test:Test = this; + for each (var obj in [text1, text2, text3, text4]) { + obj.addEventListener("focusIn", function (evt:FocusEvent):void { + trace("Focus changed: " + evt.relatedObject.name + " -> " + evt.target.name); + }); + this.stage.addChild(obj); + } + + this.stage.addEventListener("keyDown", function(evt:KeyboardEvent) { + if (evt.keyCode == 27) { + test.testStage += 1; + trace("Escape pressed, moving to stage " + test.testStage); + test.setUpTestStage(); + } else if (evt.keyCode == 9) { + trace("Tab pressed"); + } + }); + } + + function setUpTestStage() { + if (this.testStage == 0) { + // already set up + } + if (this.testStage == 1) { + this.stage.focus = text4; + } + if (this.testStage == 2) { + this.stage.focus = text1; + text2.tabEnabled = false; + } + if (this.testStage == 3) { + this.stage.focus = text1; + text1.tabEnabled = false; + text2.tabEnabled = true; + } + } + + function newTextField(i:int):TextField { + var tf:TextField = new TextField(); + tf.type = "input"; + tf.name = "text" + i; + tf.border = true; + tf.x = 0; + tf.y = i * 20; + tf.height = 20; + tf.width = 100; + return tf; + } +} +} diff --git a/tests/tests/swfs/avm2/tab_ordering_automatic_basic/input.json b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/input.json new file mode 100644 index 000000000000..5c9b519f883a --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/input.json @@ -0,0 +1,25 @@ +[ + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 } +] diff --git a/tests/tests/swfs/avm2/tab_ordering_automatic_basic/output.txt b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/output.txt new file mode 100644 index 000000000000..cc4882d844a9 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/output.txt @@ -0,0 +1,45 @@ +Tab pressed +Focus changed: text1 -> text2 +Tab pressed +Focus changed: text2 -> text3 +Tab pressed +Focus changed: text3 -> text4 +Tab pressed +Focus changed: text4 -> text1 +Tab pressed +Focus changed: text1 -> text2 +Escape pressed, moving to stage 1 +Focus changed: text2 -> text4 +Tab pressed +Focus changed: text4 -> text1 +Tab pressed +Focus changed: text1 -> text2 +Tab pressed +Focus changed: text2 -> text3 +Tab pressed +Focus changed: text3 -> text4 +Tab pressed +Focus changed: text4 -> text1 +Escape pressed, moving to stage 2 +Tab pressed +Focus changed: text1 -> text3 +Tab pressed +Focus changed: text3 -> text4 +Tab pressed +Focus changed: text4 -> text1 +Tab pressed +Focus changed: text1 -> text3 +Tab pressed +Focus changed: text3 -> text4 +Escape pressed, moving to stage 3 +Focus changed: text4 -> text1 +Tab pressed +Focus changed: text1 -> text2 +Tab pressed +Focus changed: text2 -> text3 +Tab pressed +Focus changed: text3 -> text4 +Tab pressed +Focus changed: text4 -> text2 +Tab pressed +Focus changed: text2 -> text3 diff --git a/tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.swf b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..7b666fcc114601946d56cc613739521902467bde GIT binary patch literal 1613 zcmV-T2D14>S5qm82><|i0fkjdQyWPVuBvXSkc2>h%tK()fGio09*u+_$QZ*SWaGzp z!+3TkCPG1!)YYiRqFd2jyiVhoAF#iH*u(ycjos58_9iqjv-dsC&Al-{fXQlMZ0#Jj zBdRJZ^UJKSGBc`Ak@_EmM*fP>G)C328HCXH6Te`D)?LG_ys6f-)5EsyRbclx+Y+Kv zDHcyoP6{XGg5w?(SJu|nih8M7D&+x@_s(p=PV=_6l-&pdRJqr5t&Xr9Tay79nmTli`Y|d9UR(-<_~y zo;TafYpoYQ0i}YFnS&18^T9vBoE!8&|h9!K1(e?|@g}@i|WV zb&eWs%WHA><2iedDNdLR2RcW#5ikuLKLMp%)8$M!|JUgwOuDq0eQ?AM_y)K4zuF68 zUaNu|Fd;ANYAX+OT1hXh_W4TfdQqnSvr=4Xpt>7qBylwJrtcw^0R5VHj%S-M`AvCJ6oQ!K+{Y4AMWNZ@DMXKa#T)A!!M=2~lnU6spY*xvJ$i zw6I|A0T;nh;G8b6E?kw18BT*2n$BTyYp+}^>H7U*T_c5T7o62dy>ec8ng|lyP)3Po3nC!QByQ6d*PbuFkE9D0dl~uj0td?NCS5{X*P*>LU)%ZYN zBiEf2?w5V^f2tWDDE!#(+GKLTe%)Q+ekaa-q}ha*;&)tE*MMh99}D405{gZcq2Xzq z!l`&_BsH2!q{dR?lgUYavP$BZC~7E7ha%C~aD17P5G9n7Axff=Axy~x9l1ftBvq%V zI!)CS9hsv9Q}q^A=c%eub%Cmjlq^w_j${Czr6faDi1P&KvCJ=L@9V>62XGUf`yC+ixS;L3s}KwYzwJ4G_r+4 z7@jN~#_=jfgbq=JaU`mA^{1d!NG!JW0V_!Ruj((q+PMb0lw)eN22Fkbc- z0ZJtFTM5koG<#tVrDu~mLjIk4#Ei&cM$`D5Mg3(6Gt*b}-S5gxErym8Hvs>Ibd4mV zAm#u$8=O#p6BJdA#s7{Wda|p3efKB*1HOrp9Bc36hnVAq9}bCsqq~dzsctuoYa_Td z>Q946q?qt$KvbkS=BGeZr8w@-b*dN9=S=aR_A+eFf7VMQcGKVOU8IwLVYmF}y>ybz`!9NFgK7TD-ZS{^5onty zT^(Y_IjS$2OL{$RruF)5^R`~km>IpEHM4sCj(JC~FPe+N^bNY%|5|bIivhvN#P!c{ L6LRqzn2N_kwo@hE literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.toml b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.toml new file mode 100644 index 000000000000..cf6123969a1d --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_automatic_basic/test.toml @@ -0,0 +1 @@ +num_ticks = 1 From 3d249e2b3fe9c32eed99cfb385bb3e2d66de3b2b Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 12/15] core: Add possibility to set tab_children for containers --- core/src/display_object/container.rs | 28 +++++++++++++++++++++++---- core/src/display_object/movie_clip.rs | 2 +- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/src/display_object/container.rs b/core/src/display_object/container.rs index 1450c807a22d..13c027f09b7f 100644 --- a/core/src/display_object/container.rs +++ b/core/src/display_object/container.rs @@ -136,7 +136,7 @@ pub trait TDisplayObjectContainer<'gc>: /// Get mutable access to the raw container. fn raw_container_mut(&self, gc_context: &Mutation<'gc>) -> RefMut<'_, ChildContainer<'gc>>; - /// Get a child display object by it's position in the render list. + /// Get a child display object by its position in the render list. /// /// The `index` provided here should not be confused with the `Depth`s used /// to index the depth list. @@ -144,7 +144,7 @@ pub trait TDisplayObjectContainer<'gc>: self.raw_container().get_id(index) } - /// Get a child display object by it's position in the depth list. + /// Get a child display object by its position in the depth list. /// /// The `Depth` provided here should not be confused with the `index`s used /// to index the render list. @@ -152,7 +152,7 @@ pub trait TDisplayObjectContainer<'gc>: self.raw_container().get_depth(depth) } - /// Get a child display object by it's instance/timeline name. + /// Get a child display object by its instance/timeline name. /// /// The `case_sensitive` parameter determines if we should consider /// children with different capitalizations as being distinct names. @@ -477,10 +477,26 @@ pub trait TDisplayObjectContainer<'gc>: RenderIter::from_container(self.into()) } - fn is_tab_children(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { + fn is_tab_children_avm1(&self, _context: &mut UpdateContext<'_, 'gc>) -> bool { true } + fn is_tab_children(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + if context.swf.is_action_script_3() { + self.raw_container().tab_children + } else { + self.is_tab_children_avm1(context) + } + } + + fn set_tab_children(&self, context: &mut UpdateContext<'_, 'gc>, value: bool) { + if context.swf.is_action_script_3() { + self.raw_container_mut(context.gc()).tab_children = value; + } else { + tracing::warn!("Trying to set tab_children on an AVM1 object, this has no effect") + } + } + fn fill_tab_order( &self, tab_order: &mut Vec>, @@ -630,6 +646,9 @@ pub struct ChildContainer<'gc> { /// The movie this ChildContainer belongs to. movie: Arc, + + /// Specifies whether children are present in the tab ordering. + tab_children: bool, } impl<'gc> ChildContainer<'gc> { @@ -640,6 +659,7 @@ impl<'gc> ChildContainer<'gc> { has_pending_removals: false, mouse_children: true, movie, + tab_children: true, } } diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index ba242f51ca64..2462863720d9 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -3007,7 +3007,7 @@ impl<'gc> TDisplayObjectContainer<'gc> for MovieClip<'gc> { /// _NOTE:_ /// According to the AS2 documentation, it should affect only automatic tab ordering. /// However, that does not seem to be the case, as it also affects custom ordering. - fn is_tab_children(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { + fn is_tab_children_avm1(&self, context: &mut UpdateContext<'_, 'gc>) -> bool { self.get_avm1_boolean_property(context, "tabChildren", |_| true) } } From 2ee461f846388dda6f6ac7da8f3e94b1cc0597f5 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:35:17 +0200 Subject: [PATCH 13/15] avm2: Implement DisplayObjectContainer.tabChildren --- core/src/avm2/globals/flash/display/Stage.as | 3 +- .../flash/display/display_object_container.rs | 35 ++++++++++--------- core/src/display_object/container.rs | 3 ++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/core/src/avm2/globals/flash/display/Stage.as b/core/src/avm2/globals/flash/display/Stage.as index a0d6647baf18..21e9a0bac8c7 100644 --- a/core/src/avm2/globals/flash/display/Stage.as +++ b/core/src/avm2/globals/flash/display/Stage.as @@ -149,7 +149,8 @@ package flash.display { } override public function set tabChildren(value:Boolean):void { - super.tabChildren = value; + // Docs say that this operation throws IllegalOperationError, + // but in reality this call is just ignored. } override public function set tabEnabled(value:Boolean):void { diff --git a/core/src/avm2/globals/flash/display/display_object_container.rs b/core/src/avm2/globals/flash/display/display_object_container.rs index 87171d1aa8ca..546ac7817560 100644 --- a/core/src/avm2/globals/flash/display/display_object_container.rs +++ b/core/src/avm2/globals/flash/display/display_object_container.rs @@ -9,10 +9,10 @@ use crate::avm2::object::{Object, TObject}; use crate::avm2::parameters::ParametersExt; use crate::avm2::value::Value; use crate::avm2::{ArrayObject, ArrayStorage, Error}; +use crate::avm2_stub_method; use crate::context::UpdateContext; use crate::display_object::HitTestOptions; use crate::display_object::{DisplayObject, TDisplayObject, TDisplayObjectContainer}; -use crate::{avm2_stub_getter, avm2_stub_method, avm2_stub_setter}; use std::cmp::min; /// Implements `flash.display.DisplayObjectContainer`'s native instance constructor. @@ -637,28 +637,31 @@ pub fn set_mouse_children<'gc>( pub fn get_tab_children<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, + this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_getter!( - activation, - "flash.display.DisplayObjectContainer", - "tabChildren" - ); - - Ok(true.into()) + if let Some(obj) = this + .as_display_object() + .and_then(|this| this.as_container()) + { + Ok(Value::Bool(obj.is_tab_children(&mut activation.context))) + } else { + Ok(Value::Undefined) + } } pub fn set_tab_children<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Object<'gc>, - _args: &[Value<'gc>], + this: Object<'gc>, + args: &[Value<'gc>], ) -> Result, Error<'gc>> { - avm2_stub_setter!( - activation, - "flash.display.DisplayObjectContainer", - "tabChildren" - ); + if let Some(obj) = this + .as_display_object() + .and_then(|this| this.as_container()) + { + let value = args.get_bool(0); + obj.set_tab_children(&mut activation.context, value); + } Ok(Value::Undefined) } diff --git a/core/src/display_object/container.rs b/core/src/display_object/container.rs index 13c027f09b7f..0e56aefa9e28 100644 --- a/core/src/display_object/container.rs +++ b/core/src/display_object/container.rs @@ -503,6 +503,9 @@ pub trait TDisplayObjectContainer<'gc>: context: &mut UpdateContext<'_, 'gc>, ) { if !self.is_tab_children(context) { + // AS3 docs say that objects with custom ordering (tabIndex set) + // are included even when tabChildren is false. + // Do not be fooled for that is untrue! return; } From edcc80c6f36f07695719ab3583f246f7c5933499 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 16:24:39 +0200 Subject: [PATCH 14/15] tests: Add avm2/tab_ordering_children test This test verifies the behavior of tabChildren. --- .../swfs/avm2/tab_ordering_children/Test.as | 157 ++++++++++++++++++ .../avm2/tab_ordering_children/input.json | 57 +++++++ .../avm2/tab_ordering_children/output.txt | 116 +++++++++++++ .../swfs/avm2/tab_ordering_children/test.swf | Bin 0 -> 2219 bytes .../swfs/avm2/tab_ordering_children/test.toml | 1 + 5 files changed, 331 insertions(+) create mode 100644 tests/tests/swfs/avm2/tab_ordering_children/Test.as create mode 100644 tests/tests/swfs/avm2/tab_ordering_children/input.json create mode 100644 tests/tests/swfs/avm2/tab_ordering_children/output.txt create mode 100644 tests/tests/swfs/avm2/tab_ordering_children/test.swf create mode 100644 tests/tests/swfs/avm2/tab_ordering_children/test.toml diff --git a/tests/tests/swfs/avm2/tab_ordering_children/Test.as b/tests/tests/swfs/avm2/tab_ordering_children/Test.as new file mode 100644 index 000000000000..9de1e0c8869a --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_children/Test.as @@ -0,0 +1,157 @@ +package { + +import flash.display.DisplayObject; +import flash.display.InteractiveObject; +import flash.display.Sprite; +import flash.events.KeyboardEvent; +import flash.text.TextField; +import flash.display.Sprite; +import flash.display.SimpleButton; +import flash.display.MovieClip; +import flash.events.Event; +import flash.events.FocusEvent; + +public class Test extends MovieClip { + var text1:TextField; + var text2:TextField; + var clipOuter:Sprite; + var text3:TextField; + var text4:TextField; + var clipInner:Sprite; + var text5:TextField; + var text6:TextField; + + var testStage:int = 0; + + public function Test() { + super(); + + this.text1 = this.newTextField(0); + this.text1.name = "text1"; + this.text2 = this.newTextField(1); + this.text2.name = "text2"; + this.text3 = this.newTextField(0); + this.text3.name = "text3"; + this.text4 = this.newTextField(1); + this.text4.name = "text4"; + this.text5 = this.newTextField(0); + this.text5.name = "text5"; + this.text6 = this.newTextField(1); + this.text6.name = "text6"; + + this.clipInner = this.newMovieClip(2); + this.clipInner.name = "clipInner"; + this.clipInner.addChild(this.text5); + this.clipInner.addChild(this.text6); + this.clipInner.width = 100; + this.clipInner.height = 40; + this.clipInner.y = 40; + + this.clipOuter = this.newMovieClip(2); + this.clipOuter.name = "clipOuter"; + this.clipOuter.addChild(this.text3); + this.clipOuter.addChild(this.text4); + this.clipOuter.addChild(this.clipInner); + this.clipOuter.width = 100; + this.clipOuter.height = 80; + this.clipOuter.y = 40; + + this.stage.addChild(this.text1); + this.stage.addChild(this.text2); + this.stage.addChild(this.clipOuter); + + var test:Test = this; + this.stage.addEventListener("keyDown", function(evt:KeyboardEvent) { + if (evt.keyCode == 27) { + ++test.testStage; + trace("===== Escape pressed, moving to stage " + test.testStage); + test.setUpTestStage(); + } else if (evt.keyCode == 9) { + trace("Tab pressed"); + } + }); + + this.stage.focus = this.text1; + } + + function newTextField(i:int):TextField { + var tf:TextField = new TextField(); + tf.type = "input"; + tf.border = true; + tf.addEventListener("focusIn", function(obj) { + return function (evt: FocusEvent): void { + if (evt.relatedObject != null && evt.target != null) { + trace("Focus changed at " + obj.name + ": " + evt.relatedObject.name + " -> " + evt.target.name); + } + }; + }(tf)); + this.setupObject(tf, i); + return tf; + } + + function newMovieClip(i:int):Sprite { + var mc:Sprite = new Sprite(); + mc.addEventListener("focusIn", function(obj) { + return function (evt:FocusEvent):void { + if (evt.relatedObject != null && evt.target != null) { + trace("Focus changed at " + obj.name + ": " + evt.relatedObject.name + " -> " + evt.target.name); + } + }; + }(mc)); + mc.height = 40; + return mc; + } + + function setupObject(o:DisplayObject, i:int):void { + o.x = 0; + o.y = i * 20; + o.height = 20; + o.width = 100; + } + + function setUpTestStage():void { + if (this.testStage == 0) { + // already set up + } + if (this.testStage == 1) { + this.clipOuter.tabChildren = true; + this.clipInner.tabChildren = true; + } + if (this.testStage == 2) { + this.clipOuter.tabChildren = false; + this.clipInner.tabChildren = true; + } + if (this.testStage == 3) { + this.clipOuter.tabChildren = true; + this.clipInner.tabChildren = false; + } + if (this.testStage == 4) { + this.clipOuter.tabChildren = false; + this.clipOuter.tabEnabled = false; + this.clipInner.tabChildren = true; + } + if (this.testStage == 5) { + this.clipOuter.tabChildren = false; + this.clipOuter.tabEnabled = true; + this.clipInner.tabChildren = true; + } + if (this.testStage == 6) { + this.clipOuter.tabChildren = false; + this.clipOuter.tabEnabled = undefined; + this.clipInner.tabChildren = true; + + this.text1.tabIndex = 3; + this.text3.tabIndex = 1; + this.text5.tabIndex = 2; + } + if (this.testStage == 7) { + this.clipOuter.tabChildren = true; + this.clipInner.tabChildren = false; + + this.text1.tabIndex = 3; + this.text3.tabIndex = 1; + this.text5.tabIndex = 2; + } + } +} +} diff --git a/tests/tests/swfs/avm2/tab_ordering_children/input.json b/tests/tests/swfs/avm2/tab_ordering_children/input.json new file mode 100644 index 000000000000..5d544fa72781 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_children/input.json @@ -0,0 +1,57 @@ +[ + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 27 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 }, + { "type": "KeyDown", "key_code": 9 } +] diff --git a/tests/tests/swfs/avm2/tab_ordering_children/output.txt b/tests/tests/swfs/avm2/tab_ordering_children/output.txt new file mode 100644 index 000000000000..36a3528f4a06 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_children/output.txt @@ -0,0 +1,116 @@ +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text3: text2 -> text3 +Focus changed at clipOuter: text2 -> text3 +Tab pressed +Focus changed at text4: text3 -> text4 +Focus changed at clipOuter: text3 -> text4 +Tab pressed +Focus changed at text5: text4 -> text5 +Focus changed at clipInner: text4 -> text5 +Focus changed at clipOuter: text4 -> text5 +Tab pressed +Focus changed at text6: text5 -> text6 +Focus changed at clipInner: text5 -> text6 +Focus changed at clipOuter: text5 -> text6 +Tab pressed +Focus changed at text1: text6 -> text1 +===== Escape pressed, moving to stage 1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text3: text2 -> text3 +Focus changed at clipOuter: text2 -> text3 +Tab pressed +Focus changed at text4: text3 -> text4 +Focus changed at clipOuter: text3 -> text4 +Tab pressed +Focus changed at text5: text4 -> text5 +Focus changed at clipInner: text4 -> text5 +Focus changed at clipOuter: text4 -> text5 +Tab pressed +Focus changed at text6: text5 -> text6 +Focus changed at clipInner: text5 -> text6 +Focus changed at clipOuter: text5 -> text6 +Tab pressed +Focus changed at text1: text6 -> text1 +===== Escape pressed, moving to stage 2 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text1: text2 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text1: text2 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text1: text2 -> text1 +===== Escape pressed, moving to stage 3 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text3: text2 -> text3 +Focus changed at clipOuter: text2 -> text3 +Tab pressed +Focus changed at text4: text3 -> text4 +Focus changed at clipOuter: text3 -> text4 +Tab pressed +Focus changed at text1: text4 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text3: text2 -> text3 +Focus changed at clipOuter: text2 -> text3 +===== Escape pressed, moving to stage 4 +Tab pressed +Focus changed at text1: text3 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text1: text2 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at text1: text2 -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +===== Escape pressed, moving to stage 5 +Tab pressed +Focus changed at clipOuter: text2 -> clipOuter +Tab pressed +Focus changed at text1: clipOuter -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +Tab pressed +Focus changed at clipOuter: text2 -> clipOuter +Tab pressed +Focus changed at text1: clipOuter -> text1 +Tab pressed +Focus changed at text2: text1 -> text2 +===== Escape pressed, moving to stage 6 +Tab pressed +Focus changed at text1: text2 -> text1 +Tab pressed +Tab pressed +Tab pressed +Tab pressed +Tab pressed +===== Escape pressed, moving to stage 7 +Tab pressed +Focus changed at text3: text1 -> text3 +Focus changed at clipOuter: text1 -> text3 +Tab pressed +Focus changed at text1: text3 -> text1 +Tab pressed +Focus changed at text3: text1 -> text3 +Focus changed at clipOuter: text1 -> text3 +Tab pressed +Focus changed at text1: text3 -> text1 +Tab pressed +Focus changed at text3: text1 -> text3 +Focus changed at clipOuter: text1 -> text3 +Tab pressed +Focus changed at text1: text3 -> text1 diff --git a/tests/tests/swfs/avm2/tab_ordering_children/test.swf b/tests/tests/swfs/avm2/tab_ordering_children/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..4319d5b2753acd5956ba66bf99db94a589316a9c GIT binary patch literal 2219 zcmV;c2vqk&S5qnK4FCXm0fkmea}(JWz7I)PZ_8L1u#IW3Y+)l?Z9N#<7-Nr(z%XFI zFfbE@r=`AaHAvlx)bb-WNgPsnRNkq)D;p|{Z1M-POEy_#Cr>Jqb+VcrolUmn+$+o2 znM#eSZufW2{m!}P)wi^RJpV!{`g?>i*{twJ_ndXxaJIDu9B8*JT}CPm-x7scxxqEZ{z9WJO_)?QYqO4hNch!!SG0t@+~KlhBjWgBIGHp$zJf?Wn1SS2jqZwtUHjV*J)^FK6X|7lj0YeSXvDt0GN@_tbFF=GcTW)h1DGhgD+RjdY}xCRm~gCa5TT{T zBhuhi=%Kz=dd|y^&(Rv2-03X{l2Wd~OmJP%9EIAY=d%7#(L^?P{$PeR-7fK|vRz9r zt!L92RlS@pwaltxTBka7(amPPs_o7lrV>A{U#~YzhbN9JS2{+Wkd|%uXGP$65wro=m%G4zzq*=DLTeDlu zL?(K)i3t^(P{D(i20Ok*H@&7+Z#f=kx6XYfyP@+2ljUBuLNGzCdM8k7S`KlHUfF}A zevcfO69*m^Eus24g^C=@k<`kEP7b-)#yc_T`pA)yW7P;bT1gI3gIhts*DbA7<$3@v z6mCGNbw4OqLD=c*Iyy4_r#3b=?G4A?kYrQbl^Ydat<$>Qq}iDa&8hFuTo&H>8Je5P z(!4rD^VuBD=VxhtChy5)vl&ljW=8d7v-!Lyn^&`e!|;8b8uk27k9t4X?*3yb9Ztzm zH@Y(1f1eBSawbo+x!GPX?kA^6f7qM!Up$Qm@WA-M#K5J2)WGDxRR25u%Orvc_4=4U z5DbMQ(HtXQMtzJjM*NHhnJ2;sX0(UV7$d!mo?x_((Kw?g8SQ8E6r-mZIm5^RBZG_# zF?yDfVMY{2&NDK?NP^L^Krd!wnt3v;=Q1O+jLb1Q&uE^JtBfwN*t?9bFmi*%RvEd) z$Zba6W8@BtJ!52pc|Kw>jm1h~1h*eXKC%ZF=LLd?&jEtVk-Qwk%ILM1`D2>o==GO* zGCVPQbFYv`!*}7{B&cT%-@6a%0jzac4`Drm^**e}u%5vB0M>`Fz69$jtYR78)8WlA zO9vPtk-#ESAdZlH;r>OGM3{u7L?iO$>6J=vR7$=c`C@btjbe)Z{w3taf!GrAWzw5{F%E%k&##n+gk#eaL;rF{b@2IEgTWk~S}KNaCv!_e*?@5fA}CYm z7IEP;8HY08>ey;$+}k%`eh_AeQW6f|6pelWg!O%6K>5QjwC+38plgme>;1j3_e3=swS4wK#h(~tgt(%Kg% zU52DtH|b}cJQne@!=#_V2^)*PZqj~{^gYl$?Iyj1pB^Ut)Gb2N$y-UZmxQFBiO5q| z7MaLU7s5e?TwpnB#?j<1B9cS_N`s+kFfiLt(gHGH<2*Lq=lcnyjk_=QKS{)Y2Xj>2 zPsCxaYWs4|EXX2Aa4_^o@j2Gps{7@(K@%trSD5Pvh~qJUEf~Ww?UK6%6E5C6VvESF zUD!&3>MI9ZAB!z2x4wE{^)=WMlszo=Jn=#B_zl3)?qvt0+;0Mq&c7vTUP=3Qm-Zb2 z#QT tV#dg*#jKH4i%BD?7Sl#rKAxbnonM84T^QU1`rzZ}{QF)6@LvK(9yQluM@s+z literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/tab_ordering_children/test.toml b/tests/tests/swfs/avm2/tab_ordering_children/test.toml new file mode 100644 index 000000000000..cf6123969a1d --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_children/test.toml @@ -0,0 +1 @@ +num_ticks = 1 From 2fb00f5f5a4877eb703da4cd207601e6dac12540 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 19 Apr 2024 00:32:55 +0200 Subject: [PATCH 15/15] tests: Add avm2/tab_ordering_properties This is an AVM2 version of avm1/tab_ordering_properties --- .../swfs/avm2/tab_ordering_properties/Test.as | 240 +++++++ .../avm2/tab_ordering_properties/output.txt | 671 ++++++++++++++++++ .../avm2/tab_ordering_properties/test.swf | Bin 0 -> 2503 bytes .../avm2/tab_ordering_properties/test.toml | 1 + 4 files changed, 912 insertions(+) create mode 100644 tests/tests/swfs/avm2/tab_ordering_properties/Test.as create mode 100644 tests/tests/swfs/avm2/tab_ordering_properties/output.txt create mode 100644 tests/tests/swfs/avm2/tab_ordering_properties/test.swf create mode 100644 tests/tests/swfs/avm2/tab_ordering_properties/test.toml diff --git a/tests/tests/swfs/avm2/tab_ordering_properties/Test.as b/tests/tests/swfs/avm2/tab_ordering_properties/Test.as new file mode 100644 index 000000000000..4120b6de227a --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_properties/Test.as @@ -0,0 +1,240 @@ +package { +import flash.display.MovieClip; +import flash.text.TextField; +import flash.display.SimpleButton; +import flash.display.Sprite; +import flash.display.MovieClip; +public class Test extends MovieClip { + public function Test() { + super(); + + var text:TextField = new TextField(); + var text2:TextField = new TextField(); + text2.type = "input"; + var button:SimpleButton = new SimpleButton(); + var mc:MovieClip = new MovieClip(); + var mc2:MovieClip = new MovieClip(); + mc2.buttonMode = true; + var mc3:MovieClip = new MovieClip(); + var sprite:Sprite = new Sprite(); + + trace('===== stage ====='); + this.testProperties(this.stage); + trace('===== text ====='); + this.testProperties(text); + trace('===== text type input ====='); + this.testProperties(text2); + trace('===== button ====='); + this.testProperties(button); + trace('===== movie clip ====='); + this.testProperties(mc); + trace('===== movie clip button mode true ====='); + this.testProperties(mc2); + trace('===== movie clip with index ====='); + mc3.tabIndex = 4; + this.testProperties(mc3); + trace('===== sprite ====='); + this.testProperties(sprite); + } + + function logError(f:*):void { + try { + f(); + } catch (error:Error) { + trace(' Error: ' + error); + } + } + + function printProperties(obj:*):void { + this.logError(function():void { + trace(' tabEnabled = ' + obj.tabEnabled); + }); + this.logError(function():void { + trace(' tabIndex = ' + obj.tabIndex); + }); + this.logError(function():void { + trace(' tabChildren = ' + obj.tabChildren); + }); + for (var i:String in obj) { + if (i == 'tabEnabled') { + trace(' enumerated tabEnabled'); + } + } + for (i in obj) { + if (i == 'tabIndex') { + trace(' enumerated tabIndex'); + } + } + for (i in obj) { + if (i == 'tabChildren') { + trace(' enumerated tabChildren'); + } + } + } + + function testProperties(obj:*):void { + trace(' default'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = true; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 0; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = true; + }); + + trace(' after set 1'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = false; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 4; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = false; + }); + + trace(' after set 2'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = undefined; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = undefined; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = undefined; + }); + + trace(' after set 3'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = -4; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = -4; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = -4; + }); + + trace(' after set 4'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = 2147483647; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 2147483647; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = 2147483647; + }); + + trace(' after set 5'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = 2147483648; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 2147483648; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = 2147483648; + }); + + trace(' after set 6'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = 'x'; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 'x'; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = 'x'; + }); + + trace(' after set 7'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = -2147483648; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = -2147483648; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = -2147483648; + }); + + trace(' after set 8'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = new Object(); + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = new Object(); + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = new Object(); + }); + + trace(' after set 9'); + this.printProperties(obj); + + this.logError(function():void { + trace(' set tabEnabled'); + obj.tabEnabled = 1.1; + }); + this.logError(function():void { + trace(' set tabIndex'); + obj.tabIndex = 1.1; + }); + this.logError(function():void { + trace(' set tabChildren'); + obj.tabChildren = 1.1; + }); + + trace(' after set 10'); + this.printProperties(obj); + } +} +} diff --git a/tests/tests/swfs/avm2/tab_ordering_properties/output.txt b/tests/tests/swfs/avm2/tab_ordering_properties/output.txt new file mode 100644 index 000000000000..051cb9c32be1 --- /dev/null +++ b/tests/tests/swfs/avm2/tab_ordering_properties/output.txt @@ -0,0 +1,671 @@ +===== stage ===== + default + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 1 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 2 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 3 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 4 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 5 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 6 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 7 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 8 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 9 + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabIndex + Error: Error: Error #2071: The Stage class does not implement this property or method. + set tabChildren + after set 10 + tabEnabled = false + tabIndex = -1 + tabChildren = true +===== text ===== + default + tabEnabled = false + tabIndex = -1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 1 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 2 + tabEnabled = false + tabIndex = 4 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 3 + tabEnabled = false + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 4 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 5 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 6 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 7 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 8 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 9 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 10 + tabEnabled = true + tabIndex = 1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. +===== text type input ===== + default + tabEnabled = true + tabIndex = -1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 1 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 2 + tabEnabled = false + tabIndex = 4 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 3 + tabEnabled = false + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 4 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 5 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 6 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 7 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 8 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 9 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.text.TextField. + after set 10 + tabEnabled = true + tabIndex = 1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.text.TextField and there is no default value. +===== button ===== + default + tabEnabled = true + tabIndex = -1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 1 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 2 + tabEnabled = false + tabIndex = 4 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 3 + tabEnabled = false + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 4 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 5 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 6 + tabEnabled = true + tabIndex = 2147483647 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 7 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 8 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 9 + tabEnabled = true + tabIndex = 0 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. + set tabEnabled + set tabIndex + set tabChildren + Error: ReferenceError: Error #1056: Cannot create property tabChildren on flash.display.SimpleButton. + after set 10 + tabEnabled = true + tabIndex = 1 + Error: ReferenceError: Error #1069: Property tabChildren not found on flash.display.SimpleButton and there is no default value. +===== movie clip ===== + default + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 1 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 2 + tabEnabled = false + tabIndex = 4 + tabChildren = false + set tabEnabled + set tabIndex + set tabChildren + after set 3 + tabEnabled = false + tabIndex = 0 + tabChildren = false + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + after set 4 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 5 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 6 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 7 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 8 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 9 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 10 + tabEnabled = true + tabIndex = 1 + tabChildren = true +===== movie clip button mode true ===== + default + tabEnabled = true + tabIndex = -1 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 1 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 2 + tabEnabled = false + tabIndex = 4 + tabChildren = false + set tabEnabled + set tabIndex + set tabChildren + after set 3 + tabEnabled = false + tabIndex = 0 + tabChildren = false + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + after set 4 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 5 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 6 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 7 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 8 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 9 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 10 + tabEnabled = true + tabIndex = 1 + tabChildren = true +===== movie clip with index ===== + default + tabEnabled = false + tabIndex = 4 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 1 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 2 + tabEnabled = false + tabIndex = 4 + tabChildren = false + set tabEnabled + set tabIndex + set tabChildren + after set 3 + tabEnabled = false + tabIndex = 0 + tabChildren = false + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + after set 4 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 5 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 6 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 7 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 8 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 9 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 10 + tabEnabled = true + tabIndex = 1 + tabChildren = true +===== sprite ===== + default + tabEnabled = false + tabIndex = -1 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 1 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 2 + tabEnabled = false + tabIndex = 4 + tabChildren = false + set tabEnabled + set tabIndex + set tabChildren + after set 3 + tabEnabled = false + tabIndex = 0 + tabChildren = false + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -4. + set tabChildren + after set 4 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 5 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 6 + tabEnabled = true + tabIndex = 2147483647 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 7 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + Error: RangeError: Error #2027: Parameter tabIndex must be a non-negative number; got -2147483648. + set tabChildren + after set 8 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 9 + tabEnabled = true + tabIndex = 0 + tabChildren = true + set tabEnabled + set tabIndex + set tabChildren + after set 10 + tabEnabled = true + tabIndex = 1 + tabChildren = true diff --git a/tests/tests/swfs/avm2/tab_ordering_properties/test.swf b/tests/tests/swfs/avm2/tab_ordering_properties/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..6e274895536c70a3566165e6a66bd98c8750aaea GIT binary patch literal 2503 zcmV;&2{`scS5qkv6952s0lk=ca2r=0$KTVgv^p&7up`^@CEJP}JGQl!9Vd1YM`|30 zI8BqrNt1>OvyxV}Qe8+Z+hKs3K)HtdZU=@^palko`y7~Z6(|G4CZP#1FqCoy2JrS@ z2FCo}+kILoo(})9Gi&|c@Avt>@7v!#?P|P%_~#L7egdI(jOKkE2%(2sZexTFmD8Eo zv-1m~jeM?9nT65ep;bjG%|;^Y>+9p|ljFtmN@QYYW+oy=Bhly>5Mz}q1x4BzD^v!C z=I8|TawS#HmXvI<5F!&w$zoMGJTzp?noiXwEmg}oI%PT)k#llhE-01A#P|eElupfN zisihd%t@tEE}N3bbdim*%4#w7;JUOXk7aUFW%W?R1c^q;Dmi&BUXoI)a%dqZZ-nBe zoWeRm*tEIMIpZobpct2^ny!l~>N%n-Rg<}FWmPUSpQU0(S(nOSSgaP(bfr{if<%@o z%aT(3pCX14Nlq%PRHYSpPA)8;U!rr?QuGQWg$crO0vBjkAD$TCkkcLeV3!Gk0o zmnys>ZzxvsCu&Pp6{T3P z(zscH1)eDvOLAGs$`!AU5oew1tV@tZgy?$onqRN!j(RGfr}AVup%kn~PY>-#8=^d{ zGo+NO#+v$eaO+uR6+F|h*=fzLNXZjqXqfA*(`(SciV`7zoVnu4v2wXs4vRQrrIA%8 zV^;_cI-U)=Db7fKt(Z;wNEsZC6{KWNPKOSMxMK3M)6CE<0rxXJIn`%;t)z4@DUYX$ z`AB?eG7=TV=}5Ag%_-SJTf;q?t=*&6#=L%;!i~v!{l=b7UY1kJ(IPyBvIV)^+X$T~ zC^Fn!CA%i;U}s~!VUjMrCa;kP(d;quLF$qMPm{98xNzE9xNN^MKDwICrOR>wQZDEM z8~R{p73#K4ShTY~b`YgpsODj13bfGdUE9tIwF~adGasC_Eh%8N(n{~u9j8lusC+{6LVXT^c0 zfF1I;{iqp6#tE6jSBKf?|NRN>_kugD&UzLvorCi{ocBF| zmlE*#GTgyC>#YEs3(x-O5jC|Hu1AslM&t2+}B6l zl0|DyaElz;*6Iea%)7~o5$KH%(+{(?S`YI1am90hl}r;GTphj_s!f75&#L>NI!UWOy*dq5E2|!W>J+W|_38{%ZJgER z{uhR+MYir~EXp|aaNc69ei(_`gc{=(TJSJ%Q)-Mi!u@K@YJ{_4bc@#8 zlE2XdlV}GaZ5bVDbt0r4f+ZZFy_=2lobT55ww;HIJ@TUB7!~(WaU8@mRD7gfJpZEN zV^qA4iWfjUOU3i`;uFV_#X~yWiY&X3V1YKb!!@1(dXCcfl7T*WN;y7RJ2O z^m-R%#xQujn=q}6d9Ug9KF0X8_Y-CpV?JnlJ;E5j_9$TjjCsuT`Y2^0#Orawv@z!6 zrq?GJGc)H__VJQrjs#W zH@&{W7{B&S!gMj_JEqrnDKlmPukR72n=wByy`E-_Px~QZdKmL#)9V?=__d!9rk60i zus2lG>l$SeZHsLP?5-0m#IRqOcF)#fKJ6yK`WW_0)A3hzm|y!f!TQ<4o-<81wz?eUpj(=i|Px~`r!i>3X+WnO=e(i6B*=^xmZjFa4JjouK^Y~=#ad}d^8}{-s z`t?7hlBeQAJG`$>t1-cNS}v(EyAfVcV-6#H0941RDq*UY)tJ+$r_`9s2v^itlM&`X z^%APeo2sH3a~t)F8f!Mfbv5QO!dHRn1XaD-R6V4|yhiB20Z5C1ya(b|BmMxyyNvilM0%1+KU^pM2p|Ci`544)M*Jki?MD0=BE6eRKU*jL z93UMA@+F9aM*KC1JB|2TM0$!!zg;JN3Xm=X`98$mM*Jg)dyM#}M0yXE{;W>=b3l3x z