Merge commit 'd90867218312b97113ce7c50c5232f6e5ceee9be'
diff --git a/ApproveSDK.xml b/ApproveSDK.xml
index 08134b7..903655d 100644
--- a/ApproveSDK.xml
+++ b/ApproveSDK.xml
@@ -54,10 +54,10 @@
 	
     <property name="src.rat.report" value="${basedir}/rat-report-src.txt"/>
     <property name="bin.rat.report" value="${basedir}/rat-report-bin.txt"/>
-    <property name="apache.rat.jar" value="apache-rat-0.11.jar" />
-    <property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.11.jar" />
-    <property name="apache.rat.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat/0.11" />
-    <property name="apache.rat.tasks.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat-tasks/0.11" />
+    <property name="apache.rat.jar" value="apache-rat-0.12.jar" />
+    <property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.12.jar" />
+    <property name="apache.rat.url" value="http://central.maven.org/maven2/org/apache/rat/apache-rat/0.12" />
+    <property name="apache.rat.tasks.url" value="http://central.maven.org/maven2/org/apache/rat/apache-rat-tasks/0.12" />
 	   
     <property file="${basedir}/approvesdk.properties"/>
     
@@ -325,6 +325,7 @@
                 <exclude name="licenseParts/NOTICE.asc"/>
                 <exclude name="licenseParts/NOTICE.base"/>
                 <exclude name="licenseParts/NOTICE.pb"/>
+                <exclude name="licenseParts/saxon9-NOTICES/*"/>
                 <exclude name="modules/thirdparty/batik/lib/**/LICENSE*.txt"/>
                 <exclude name="modules/thirdparty/batik/lib/**/README*.txt"/>
                 <exclude name="frameworks/projects/flatspark/src/flatspark/assets/fonts/**/OFL.txt"/>
diff --git a/GIT-TEST.txt b/GIT-TEST.txt
index 8755d36..59972d6 100644
--- a/GIT-TEST.txt
+++ b/GIT-TEST.txt
@@ -1,5 +1,5 @@
 Hope that it works and I'll be ready to change the world ;-) [okrueger]
-
+ 
 Test by piotrz :)
 junheider is Top Posting this file�people hate this on mailing lists.
 
diff --git a/KEYS b/KEYS
index 6651922..b9f884f 100644
--- a/KEYS
+++ b/KEYS
@@ -356,3 +356,119 @@
 f/WyocyIyPkr7HH0xI7PLn0=
 =nsEL
 -----END PGP PUBLIC KEY BLOCK-----
+pub   rsa4096/EDF6613E 2016-09-09
+uid         [ultimate] Josh Tynjala (CODE SIGNING KEY) <joshtynjala@apache.org>
+sig 3        EDF6613E 2016-09-09  Josh Tynjala (CODE SIGNING KEY) <joshtynjala@apache.org>
+sub   rsa4096/D5780FEF 2016-09-09
+sig          EDF6613E 2016-09-09  Josh Tynjala (CODE SIGNING KEY) <joshtynjala@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+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
+CR1nUan0cN8sLesf4hK5RUWpX6ww0g==
+=mfLU
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub  4096R/05061FC8 2017-06-17
+Key fingerprint = 4499 8F3E 2427 27E9 4C4B  ADEB 6B0A 7EC9 0506 1FC8
+uid  Piotr Zarzycki (CODE SIGNING KEY) <piotrz@apache.org>
+sub  4096R/E7EF0C6D 2017-06-17
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG 2.0.30
+
+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
+ZGs7Ibn/LbgXcM6jdzDFLOHfulZ/
+=GBzo
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/LICENSE b/LICENSE
index 3faa057..3de99e1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -258,6 +258,9 @@
 The Lato font is available under OFL. For details
 see frameworks/projects/flatspark/src/flatspark/assets/fonts/lato
 
+The AwesomeUtils is available under MIT. For details
+see frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
+
 This product includes a fork of Apache Batik which includes files available under
 the 2002 W3C Software license.  For details, see 
 modules/thirdparty/batik/LICENSE.W3C2002.
diff --git a/README b/README
index 0bd9999..7aee7d1 100644
--- a/README
+++ b/README
@@ -215,6 +215,10 @@
 On Windows, download the Adobe Extension Manager from:
 
     http://download.macromedia.com/pub/dw_exchange/extension_manager/win/AdobeExtensionManager5All.zip
+	
+On Windows 10, download the Adobe Extension Manager CS6 from:
+
+	http://download.macromedia.com/pub/dw_exchange/extension_manager/win/AdobeExtensionManager6_0_8All.zip
 
 and set ADOBE_EXTENSION_MANAGER to the absolute path of
 'Adobe Extension Manager CS5.exe'
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 5aaadc3..81d4b72 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,3 +1,45 @@
+Apache Flex 4.16.1
+==================
+
+AIR and Flash Player Support
+----------------------------
+- Support Flash Player 21.0, 22.0, 23.0, 24.0, 25.0, 26.0 and 27.0
+- Support for AIR 21.0, 22.0, 23.0, 24.0, 25.0, 26.0 and 27.0
+
+Bug Fixes
+---------
+FLEX-35364 Flex installer.xml is failing occasionally
+FLEX-35329 Initializing member variable/constant that is [Deprecated]
+            incorrectly throws extra warning
+FLEX-35321 LayoutManager initializes components which are no longer on stage
+FLEX-35267 Spark DataGrid's GridHeaderViewLayout.getHeaderIndexAt() returns wrong header index when leftPadding is comparable to a column's width
+FLEX-27509 AdvancedListBase itemMaskFreeList is null 
+
+Known Issues
+------------
+
+Adobe Flash Builder Integration
+
+Adobe Flash Builder 4.7 and Adobe Flash Builder 4.6 both contain a bug where,
+when generating the .mxml file for a new project that uses Apache Flex SDK
+4.10.0 or later Spark Application, Flash Builder will incorrectly insert the
+attribute:
+
+    layout="absolute"
+
+This results in a compile error in the new project.  The remedy is to simply
+remove the errant attribute.
+
+The following wiki page has been set up to contain the latest news on Adobe's
+attempt to correct this problem:
+
+    https://cwiki.apache.org/confluence/display/FLEX/Adobe+Flash+Builder+'New+Project'+Bug
+
+Adobe has provided a patch for Flash Builder 4.7 that resolves this issue:
+
+    http://helpx.adobe.com/flash-builder/kb/flex-new-project-issue--.html
+
+
 Apache Flex 4.16.0
 ==================
 
diff --git a/build.properties b/build.properties
index 0ba13bb..fb505da 100644
--- a/build.properties
+++ b/build.properties
@@ -18,8 +18,8 @@
 ################################################################################
 
 # flex-sdk-description values
-release = Apache Flex 4.16.0
-release.version = 4.16.0
+release = Apache Flex 4.16.1
+release.version = 4.16.1
 
 # override on command line with -Dbuild.number=999 or in local.properties
 build.number = 0
diff --git a/frameworks/build.xml b/frameworks/build.xml
index 500a186..2e71195 100644
--- a/frameworks/build.xml
+++ b/frameworks/build.xml
@@ -142,6 +142,7 @@
         <antcall target="spark-test"/>
         <antcall target="advancedgrids-test"/>
         <antcall target="framework-test"/>
+        <antcall target="mx-test"/>
     </target>
 
 	<target name="flex-config" depends="playerglobal-setswfversion" description="Copy the flex/air/airmobile config templates to flex/air/airmobile-config.xml and inject version numbers">
@@ -551,6 +552,9 @@
     <target name="framework-test" description="Tests for 'framework' project">
         <ant dir="${basedir}/projects/framework" target="test"/>
     </target>
+    <target name="mx-test" description="Tests for the 'mx' project">
+        <ant dir="${basedir}/projects/mx" target="test"/>
+    </target>
 
     <target name="experimental" description="Clean build of experimental.swc">
         <ant dir="${basedir}/projects/experimental"/>
diff --git a/frameworks/projects/advancedgrids/src/mx/core/Version.as b/frameworks/projects/advancedgrids/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/advancedgrids/src/mx/core/Version.as
+++ b/frameworks/projects/advancedgrids/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/airframework/src/mx/core/Version.as b/frameworks/projects/airframework/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/airframework/src/mx/core/Version.as
+++ b/frameworks/projects/airframework/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/airspark/src/spark/core/Version.as b/frameworks/projects/airspark/src/spark/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/airspark/src/spark/core/Version.as
+++ b/frameworks/projects/airspark/src/spark/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/apache/src/core/Version.as b/frameworks/projects/apache/src/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/apache/src/core/Version.as
+++ b/frameworks/projects/apache/src/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation/src/mx/core/Version.as b/frameworks/projects/automation/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation/src/mx/core/Version.as
+++ b/frameworks/projects/automation/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_agent/src/mx/core/Version.as b/frameworks/projects/automation_agent/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation_agent/src/mx/core/Version.as
+++ b/frameworks/projects/automation_agent/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_air/src/mx/core/Version.as b/frameworks/projects/automation_air/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation_air/src/mx/core/Version.as
+++ b/frameworks/projects/automation_air/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_dmv/src/mx/core/Version.as b/frameworks/projects/automation_dmv/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation_dmv/src/mx/core/Version.as
+++ b/frameworks/projects/automation_dmv/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as b/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
index 0b10511..9782bf9 100644
--- a/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
+++ b/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
@@ -24,4 +24,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_spark/src/mx/core/Version.as b/frameworks/projects/automation_spark/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation_spark/src/mx/core/Version.as
+++ b/frameworks/projects/automation_spark/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/automation_spark/src/spark/core/Version.as b/frameworks/projects/automation_spark/src/spark/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/automation_spark/src/spark/core/Version.as
+++ b/frameworks/projects/automation_spark/src/spark/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/charts/src/mx/core/Version.as b/frameworks/projects/charts/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/charts/src/mx/core/Version.as
+++ b/frameworks/projects/charts/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as b/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as
index 09f9cb2..e9007c3 100644
--- a/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as
+++ b/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as
@@ -45,15 +45,10 @@
 		public static const Concrete:uint = 0x95A5A6;
 		public static const Asbestos:uint = 0x7F8C8D;
 		
-		public function ColorUtils()
-		{
-			
-		}		
-		
 		public static function ButtonColor(brand:int, estado:State):uint
 		{
 			// All the possible colors
-			var cores:Array = new Array(
+			var cores:Array = [
 				ButtonColorEnum.PrimaryUp, ButtonColorEnum.PrimaryHover, ButtonColorEnum.PrimaryDown, ButtonColorEnum.PrimaryDisabled,
 				ButtonColorEnum.SuccessUp, ButtonColorEnum.SuccessHover, ButtonColorEnum.SuccessDown, ButtonColorEnum.SuccessDisabled,
 				ButtonColorEnum.WarningUp, ButtonColorEnum.WarningHover, ButtonColorEnum.WarningDown, ButtonColorEnum.WarningDisabled,
@@ -61,7 +56,7 @@
 				ButtonColorEnum.DefaultUp, ButtonColorEnum.DefaultHover, ButtonColorEnum.DefaultDown, ButtonColorEnum.DefaultDisabled,
 				ButtonColorEnum.InfoUp, ButtonColorEnum.InfoHover, ButtonColorEnum.InfoDown, ButtonColorEnum.InfoDisabled,
 				ButtonColorEnum.DangerUp, ButtonColorEnum.DangerHover, ButtonColorEnum.DangerDown, ButtonColorEnum.DangerDisabled
-				);
+				];
 			
 			// Map all the allowed states
 			var numeroEstado:int = 1;
@@ -80,11 +75,8 @@
 					numeroEstado = 3;
 					break;
 			}
-			
-			var posicao:int = 1;
-			posicao = 4 * (brand - 1) + (numeroEstado - 1); 
-			
-			return cores[posicao];
+
+			return cores[4 * (brand - 1) + (numeroEstado - 1)];
 		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/framework/src/mx/core/FlexVersion.as b/frameworks/projects/framework/src/mx/core/FlexVersion.as
index 08650af..21a99b3 100644
--- a/frameworks/projects/framework/src/mx/core/FlexVersion.as
+++ b/frameworks/projects/framework/src/mx/core/FlexVersion.as
@@ -56,9 +56,23 @@
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
-    public static const CURRENT_VERSION:uint = 0x04100000;
+    public static const CURRENT_VERSION:uint = 0x04100001;
 	
-		/** 
+	/** 
+	 *  The <code>compatibilityVersion</code> value of Flex 4.16.1,
+	 *  encoded numerically as a <code>uint</code>.
+	 *  Code can compare this constant against
+	 *  the <code>compatibilityVersion</code>
+	 *  to implement version-specific behavior.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 11
+	 *  @playerversion AIR 3
+	 *  @productversion Apache Flex 4.16.1
+	 */
+	public static const VERSION_4_16_1:uint = 0x04100001;
+	
+	/** 
 	 *  The <code>compatibilityVersion</code> value of Flex 4.16,
 	 *  encoded numerically as a <code>uint</code>.
 	 *  Code can compare this constant against
diff --git a/frameworks/projects/framework/src/mx/core/Version.as b/frameworks/projects/framework/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/framework/src/mx/core/Version.as
+++ b/frameworks/projects/framework/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/framework/src/mx/managers/LayoutManager.as b/frameworks/projects/framework/src/mx/managers/LayoutManager.as
index 45395ac..131838e 100644
--- a/frameworks/projects/framework/src/mx/managers/LayoutManager.as
+++ b/frameworks/projects/framework/src/mx/managers/LayoutManager.as
@@ -19,14 +19,10 @@
 
 package mx.managers
 {
-import flash.display.DisplayObject;
-import flash.display.Sprite;
 import flash.display.Stage;
 import flash.events.Event;
 import flash.events.EventDispatcher;
 
-import mx.core.ILayoutElement;
-import mx.core.UIComponent;
 import mx.core.UIComponentGlobals;
 import mx.core.mx_internal;
 import mx.events.DynamicEvent;
@@ -780,7 +776,7 @@
      */
     private function doPhasedInstantiation():void
     {
-        // trace(">>DoPhasedInstantation");
+        // trace(">>DoPhasedInstantiation");
 
         // If phasing, do only one phase: validateProperties(),
         // validateSize(), or validateDisplayList().
@@ -846,10 +842,14 @@
 			var obj:ILayoutManagerClient = ILayoutManagerClient(updateCompleteQueue.removeLargest());
             while (obj)
             {
-                if (!obj.initialized && obj.processedDescriptors)
-                    obj.initialized = true;
-                if (obj.hasEventListener(FlexEvent.UPDATE_COMPLETE))
-                    obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
+                if(obj.nestLevel)
+                {
+                    if (!obj.initialized && obj.processedDescriptors)
+                        obj.initialized = true;
+                    if (obj.hasEventListener(FlexEvent.UPDATE_COMPLETE))
+                        obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
+                }
+
                 obj.updateCompletePendingFlag = false;
                 obj = ILayoutManagerClient(updateCompleteQueue.removeLargest());
             }
@@ -927,7 +927,6 @@
 		var lastCurrentObject:ILayoutManagerClient = currentObject;
 		
         var obj:ILayoutManagerClient;
-        var i:int = 0;
         var done:Boolean = false;
         var oldTargetLevel:int = targetLevel;
 
@@ -1094,12 +1093,16 @@
                 obj = ILayoutManagerClient(updateCompleteQueue.removeLargestChild(target));
                 while (obj)
                 {
-                    if (!obj.initialized)
-                        obj.initialized = true;
-                    
-                    if (obj.hasEventListener(FlexEvent.UPDATE_COMPLETE))
-                        obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
-                    obj.updateCompletePendingFlag = false;
+                    if(obj.nestLevel)
+                    {
+                        if (!obj.initialized)
+                            obj.initialized = true;
+
+                        if (obj.hasEventListener(FlexEvent.UPDATE_COMPLETE))
+                            obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
+                    }
+
+                        obj.updateCompletePendingFlag = false;
                     obj = ILayoutManagerClient(updateCompleteQueue.removeLargestChild(target));
                 }
             }
diff --git a/frameworks/projects/framework/tests/mx/managers/LayoutManager_FLEX_35321_Tests.as b/frameworks/projects/framework/tests/mx/managers/LayoutManager_FLEX_35321_Tests.as
new file mode 100644
index 0000000..1c830f4
--- /dev/null
+++ b/frameworks/projects/framework/tests/mx/managers/LayoutManager_FLEX_35321_Tests.as
@@ -0,0 +1,295 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.managers {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.core.UIComponentGlobals;
+    import mx.core.mx_internal;
+    import mx.events.FlexEvent;
+
+    import org.flexunit.assertThat;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertNotNull;
+    import org.flexunit.asserts.assertNull;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    use namespace mx_internal;
+
+    public class LayoutManager_FLEX_35321_Tests
+    {
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private var _objectWhichIsRemovedAtValidation:SomeComponent;
+        private var _creationCompleteCalls:int;
+
+        [Before]
+        public function setUp():void
+        {
+            _creationCompleteCalls = 0;
+            _objectWhichIsRemovedAtValidation = new SomeComponent();
+            _objectWhichIsRemovedAtValidation.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
+            UIImpersonator.addElement(_objectWhichIsRemovedAtValidation);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            UIImpersonator.removeAllChildren();
+            _objectWhichIsRemovedAtValidation = null;
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  Test method
+        //
+        //--------------------------------------------------------------------------
+
+        [Test]
+        public function test_object_removed_from_stage_via_code_is_not_initialized():void
+        {
+            //given
+            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = false;
+            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = true;
+
+            //when
+            _objectWhichIsRemovedAtValidation.invalidateProperties();
+            _objectWhichIsRemovedAtValidation.invalidateSize();
+            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
+            _objectWhichIsRemovedAtValidation.validateNow();
+
+            //then
+            then_assert_not_initialized();
+            assert_validation_count(1, 0, 0);
+        }
+
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  Test method
+        //
+        //--------------------------------------------------------------------------
+
+        [Test(async, timeout=500)]
+        public function test_object_removed_from_stage_via_user_action_is_not_initialized():void
+        {
+            //given
+            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = true;
+            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = false;
+
+            //when
+            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
+            _objectWhichIsRemovedAtValidation.invalidateProperties();
+            _objectWhichIsRemovedAtValidation.invalidateSize();
+
+            //then wait 1 frame
+            noEnterFramesRemaining = 1;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_remove_from_stage_via_callLater, 300, {nextStep:then_assert_not_initialized_but_partially_validated, afterNumFrames:3});
+        }
+
+
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  Test method
+        //
+        //--------------------------------------------------------------------------
+
+        [Test(async, timeout=750)]
+        public function test_object_removed_from_stage_then_readded_is_initialized_once():void
+        {
+            //given
+            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = true;
+            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = false;
+
+            //when
+            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
+            _objectWhichIsRemovedAtValidation.invalidateProperties();
+            _objectWhichIsRemovedAtValidation.invalidateSize();
+
+            //then wait 1 frame
+            noEnterFramesRemaining = 1;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_remove_from_stage_via_callLater, 300, {nextStep:then_readd_object, afterNumFrames:1});
+        }
+
+        private function then_readd_object(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertNull("The object was actually not removed from stage. Huh?", _objectWhichIsRemovedAtValidation.parent);
+
+            //when
+            UIImpersonator.addElement(_objectWhichIsRemovedAtValidation);
+
+            //then wait 3 frames, to make sure validation is done
+            noEnterFramesRemaining = 3;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_assert_one_initialization_only, 400);
+        }
+
+        private function then_assert_one_initialization_only(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertNotNull("The object should be on stage...", _objectWhichIsRemovedAtValidation.parent);
+            assertThat("If it's on stage, the nestLevel should be positive", _objectWhichIsRemovedAtValidation.nestLevel > 0);
+            assertEquals("When validation is interrupted half-way it should be complete once the object is re-added to stage", 1, _creationCompleteCalls);
+            assert_validation_count(2, 2, 1);
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  Shared test methods
+        //
+        //--------------------------------------------------------------------------
+
+        private function then_remove_from_stage_via_callLater(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertEquals("The first validation step should have completed by now", 1, _objectWhichIsRemovedAtValidation.numValidatePropertiesCalls);
+            assertEquals("But not validateSize()", 0, _objectWhichIsRemovedAtValidation.numValidateSizeCalls);
+            assertEquals("Nor validateDisplayList()", 0, _objectWhichIsRemovedAtValidation.numValidateDisplayListCalls);
+
+            //given
+            const whereToGoNext:Function = passThroughData.nextStep as Function;
+            const afterHowManyFrames:int = passThroughData.afterNumFrames as int;
+
+            //when
+            _objectWhichIsRemovedAtValidation.pretendUserAskedForComponentRemovalInNextFrame();
+
+            //then wait
+            noEnterFramesRemaining = afterHowManyFrames;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, whereToGoNext, 300);
+        }
+
+        private function then_assert_not_initialized(event:Event = null, passThroughData:Object = null):void
+        {
+            //then
+            assertNull("The object was actually not removed from stage. Huh?", _objectWhichIsRemovedAtValidation.parent);
+            assertEquals("Yep, this is the bug. Why call initialized=true on an object that's not on stage?", 0, _creationCompleteCalls);
+        }
+
+        private function then_assert_not_initialized_but_partially_validated(event:Event = null, passThroughData:Object = null):void
+        {
+            //then
+            then_assert_not_initialized(event, passThroughData);
+            assert_validation_count(1, 1, 0);
+        }
+
+        private function assert_validation_count(numPropertiesValidations:int = 1, numSizeValidations:int = 1, numDisplayListValidations:int = 1):void
+        {
+            //then
+            assertEquals("Properties should have been validated", numPropertiesValidations, _objectWhichIsRemovedAtValidation.numValidatePropertiesCalls);
+            assertEquals("Size should have been validated", numSizeValidations, _objectWhichIsRemovedAtValidation.numValidateSizeCalls);
+            assertEquals("Display list should have been validated", numDisplayListValidations, _objectWhichIsRemovedAtValidation.numValidateDisplayListCalls);
+        }
+
+
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+
+        private function onCreationComplete(event:FlexEvent):void
+        {
+            _creationCompleteCalls++;
+        }
+    }
+}
+
+import mx.core.IVisualElementContainer;
+import mx.core.UIComponent;
+
+class SomeComponent extends UIComponent
+{
+    private var _removeFromStageOnValidateProperties:Boolean = false;
+    private var _numValidatePropertiesCalls:int = 0;
+    private var _numValidateSizeCalls:int = 0;
+    private var _numValidateDisplayListCalls:int = 0;
+
+    override public function validateProperties():void
+    {
+        super.validateProperties();
+        _numValidatePropertiesCalls++;
+        if(_removeFromStageOnValidateProperties)
+            removeFromStage();
+    }
+
+    override public function validateSize(recursive:Boolean = false):void
+    {
+        super.validateSize(recursive);
+        _numValidateSizeCalls++;
+    }
+
+    override public function validateDisplayList():void
+    {
+        super.validateDisplayList();
+        _numValidateDisplayListCalls++;
+    }
+
+    private function removeFromStage():void
+    {
+        if(this.parent)
+        {
+            if(this.parent is IVisualElementContainer)
+                IVisualElementContainer(this.parent).removeElement(this);
+            else
+                this.parent.removeChild(this);
+        }
+    }
+
+    public function pretendUserAskedForComponentRemovalInNextFrame():void
+    {
+        callLater(removeFromStage);
+    }
+
+    public function set removeFromStageOnValidateProperties(value:Boolean):void
+    {
+        _removeFromStageOnValidateProperties = value;
+    }
+
+    public function get numValidateDisplayListCalls():int
+    {
+        return _numValidateDisplayListCalls;
+    }
+
+    public function get numValidateSizeCalls():int
+    {
+        return _numValidateSizeCalls;
+    }
+
+    public function get numValidatePropertiesCalls():int
+    {
+        return _numValidatePropertiesCalls;
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mx/build.xml b/frameworks/projects/mx/build.xml
index f1ad0ad..259c7b6 100644
--- a/frameworks/projects/mx/build.xml
+++ b/frameworks/projects/mx/build.xml
@@ -229,4 +229,10 @@
         <delete dir="${FLEX_HOME}/tempDoc" failonerror="false" includeEmptyDirs="true"/>
         <delete file="${basedir}/bundles/en_US/packages.dita" failonerror="false"/>
     </target>
+
+    <target name="test" description="Runs the FlexUnit tests for this project">
+        <ant antfile="${FLEX_HOME}/flexunit-tests.xml">
+            <property name="project.root" value="${basedir}"/>
+        </ant>
+    </target>
 </project>
diff --git a/frameworks/projects/mx/src/mx/controls/Tree.as b/frameworks/projects/mx/src/mx/controls/Tree.as
index 5f9215a..5bf874f 100644
--- a/frameworks/projects/mx/src/mx/controls/Tree.as
+++ b/frameworks/projects/mx/src/mx/controls/Tree.as
@@ -1783,7 +1783,7 @@
             // is the item on screen?
             if (visibleData[uid])
             {
-                //find the rowindex of the row after the open thats opening/closing
+                //find the row index of the first row after the one that's opening/closing
                 var n:int = listItems.length;
                 for (rowIndex = 0; rowIndex < n; rowIndex++)
                 {
diff --git a/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalCollectionView.as b/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalCollectionView.as
index 5f357b0..59fe7e8 100644
--- a/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalCollectionView.as
+++ b/frameworks/projects/mx/src/mx/controls/treeClasses/HierarchicalCollectionView.as
@@ -267,7 +267,7 @@
 			var modelCursor:IViewCursor = treeData.createCursor();
 			if (modelCursor.beforeFirst)
 			{
-				// indicates that an IPE occured on the first item
+				// indicates that an IPE occurred on the first item
 				return treeData.length;
 			}
 			while (!modelCursor.afterLast)
@@ -315,8 +315,7 @@
 			parentMap[uid] = parent;
 			if (node != null &&
 				openNodes[uid] &&
-				dataDescriptor.isBranch(node, treeData) &&
-				dataDescriptor.hasChildren(node, treeData))
+				dataDescriptor.isBranch(node, treeData))
 			{
 				childNodes = getChildren(node);
 				if (childNodes != null)
@@ -432,7 +431,7 @@
     
     /**
 	 * @private
-	 * delegate getchildren in order to add event listeners for nested collections
+	 * delegate getChildren in order to add event listeners for nested collections
 	 */
 	private function getChildren(node:Object):ICollectionView
 	{
diff --git a/frameworks/projects/mx/src/mx/core/Version.as b/frameworks/projects/mx/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/mx/src/mx/core/Version.as
+++ b/frameworks/projects/mx/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Collection_Length_Tests.as b/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Collection_Length_Tests.as
new file mode 100644
index 0000000..4b32a32
--- /dev/null
+++ b/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Collection_Length_Tests.as
@@ -0,0 +1,220 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.controls {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.collections.ArrayCollection;
+    import mx.core.mx_internal;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    use namespace mx_internal;
+
+    public class Tree_FLEX_18746_Collection_Length_Tests
+    {
+        private static var noEnterFramesToWait:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:Tree_;
+        private static var Sam:TreeItem;
+        private static var Ana:TreeItem;
+        private static var Jenny:TreeItem;
+        private static var Marc:TreeItem;
+        private static var parentJill:TreeItem;
+        private static var parentJohn:TreeItem;
+
+
+        [Before]
+        public function setUp():void
+        {
+            Sam = new TreeItem("Sam");
+            Ana = new TreeItem("Ana");
+            Jenny = new TreeItem("Jenny");
+            Marc = new TreeItem("Marc");
+
+            _sut = new Tree_();
+            _sut.width = 200;
+            _sut.height = 200;
+
+            UIImpersonator.addChild(_sut);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            UIImpersonator.removeAllChildren();
+            _sut = null;
+        }
+
+
+        [Test(async, timeout=300)]
+        public function test_opening_closing_with_both_parents_having_at_least_one_child():void
+        {
+            //given
+            parentJill = new TreeItem("Jill", new ArrayCollection([Marc]));
+            parentJohn = new TreeItem("John", new ArrayCollection([Sam]));
+
+            const dataProvider:ArrayCollection = new ArrayCollection();
+            dataProvider.addItem(parentJill);
+            dataProvider.addItem(parentJohn);
+
+            //when
+            _sut.dataProvider = dataProvider;
+
+            //then wait a few frames
+            noEnterFramesToWait = 2;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_expand_and_contract, 250);
+        }
+
+        [Test(async, timeout=300)]
+        public function test_opening_closing_with_Jill_having_no_children_to_begin_with():void
+        {
+            //given
+            parentJill = new TreeItem("Jill", new ArrayCollection());
+            parentJohn = new TreeItem("John", new ArrayCollection([Sam]));
+
+            const dataProvider:ArrayCollection = new ArrayCollection();
+            dataProvider.addItem(parentJill);
+            dataProvider.addItem(parentJohn);
+
+            //when
+            _sut.dataProvider = dataProvider;
+
+            //then wait a few frames
+            noEnterFramesToWait = 2;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_expand_and_contract, 250);
+        }
+
+        private static function then_expand_and_contract(event:Event, passThroughData:Object):void
+        {
+            //given
+            var currentLength:int = _sut.collectionLength_; //current length is correct
+
+            //then
+            assertEquals(2, currentLength);
+
+            //when
+            _sut.expandItem(parentJohn, true, false, true);
+            currentLength += parentJohn.children.length;
+
+            //then
+            assertEquals(currentLength, _sut.collectionLength_);
+
+            //when
+            _sut.expandItem(parentJill, true, false, true);
+            currentLength += parentJill.children.length;
+
+            //then
+            assertEquals(currentLength, _sut.collectionLength_);
+
+            //when
+            parentJohn.children.addItem(Jenny);
+            currentLength += 1;
+
+            //then
+            assertEquals(currentLength, _sut.collectionLength_);
+
+            //when
+            _sut.expandItem(parentJohn, false, false, true);
+            currentLength -= parentJohn.children.length;
+
+            //then
+            assertEquals(currentLength, _sut.collectionLength_);
+
+            //when
+            parentJill.children.addItem(Ana);
+            currentLength += 1;
+
+            //then
+            assertEquals(currentLength, _sut.collectionLength_);
+        }
+
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesToWait)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}
+
+import mx.controls.Tree;
+import mx.controls.treeClasses.HierarchicalCollectionView;
+
+class Tree_ extends Tree
+{
+    public function getHierarchicalCollection():HierarchicalCollectionView
+    {
+        return super.collection as HierarchicalCollectionView;
+    }
+
+    public function get collectionLength_():int
+    {
+        return getHierarchicalCollection().length;
+    }
+}
+
+import mx.collections.ArrayCollection;
+
+class TreeItem {
+    private var _label:String;
+    private var _children:ArrayCollection;
+
+    public function TreeItem(label:String, children:ArrayCollection = null)
+    {
+        this.label = label;
+        this.children = children;
+    }
+
+    [Bindable]
+    public function set label(label:String):void
+    {
+        _label = label;
+    }
+
+    public function get label():String
+    {
+        return _label;
+    }
+
+    [Bindable]
+    public function set children(children:ArrayCollection):void
+    {
+        _children = children;
+    }
+
+    public function get children():ArrayCollection
+    {
+        return _children;
+    }
+
+    public function toString():String
+    {
+        return "TreeItem{_label=" + String(_label) + "}";
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as b/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as
new file mode 100644
index 0000000..38bd4db
--- /dev/null
+++ b/frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as
@@ -0,0 +1,146 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.controls {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.collections.ArrayCollection;
+    import mx.core.mx_internal;
+
+    import org.flexunit.assertThat;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    use namespace mx_internal;
+
+    public class Tree_FLEX_18746_Tests
+    {
+        private static var noEnterFramesToWait:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:Tree;
+        private static var child:Object = {label: "Item"};
+        private static var parent0:Object;
+        private static var parent1:Object;
+
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new Tree();
+            _sut.width = 200;
+            _sut.height = 200;
+
+            parent0 = {label: "Folder 0", children: new ArrayCollection()};
+            parent1 = {label: "Folder 1", children: new ArrayCollection([child])};
+
+            UIImpersonator.addChild(_sut);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            UIImpersonator.removeAllChildren();
+            _sut = null;
+        }
+
+
+        [Test(async, timeout=1000)]
+        public function test_closing_previously_opened_folder_with_0_children_without_animation_does_not_throw_fatal():void
+        {
+            //given
+            const dataProvider:ArrayCollection = new ArrayCollection();
+            dataProvider.addItem(parent0);
+            dataProvider.addItem(parent1);
+
+            //when
+            _sut.dataProvider = dataProvider;
+
+            //then wait a few frames
+            noEnterFramesToWait = 2;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_expand_second_folder, 300, {useAnimation:false});
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_closing_previously_opened_folder_with_0_children_using_animation_does_not_throw_fatal():void
+        {
+            //given
+            const dataProvider:ArrayCollection = new ArrayCollection();
+            dataProvider.addItem(parent0);
+            dataProvider.addItem(parent1);
+
+            //when
+            _sut.dataProvider = dataProvider;
+
+            //then wait a few frames
+            noEnterFramesToWait = 2;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_expand_second_folder, 300, {useAnimation:true});
+        }
+
+
+        private function then_expand_second_folder(event:Event, passThroughData:Object):void
+        {
+            //when
+            _sut.expandItem(parent1, true, passThroughData.useAnimation, true);
+
+            //then wait a bit
+            noEnterFramesToWait = 5;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_move_child_to_first_parent_and_expand_it, 500, passThroughData);
+        }
+
+        private function then_move_child_to_first_parent_and_expand_it(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertThat(_sut.isItemOpen(parent1));
+
+            //when
+            ArrayCollection(parent1.children).removeItemAt(0);
+            _sut.expandItem(parent0, true, passThroughData.useAnimation, true);
+            ArrayCollection(parent0.children).addItem(child);
+
+            //then wait a bit
+            noEnterFramesToWait = 1;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_contract_second_folder, 200, passThroughData);
+        }
+
+        private static function then_contract_second_folder(event:Event, passThroughData:Object):void
+        {
+            //when
+            _sut.expandItem(parent1, false, passThroughData.useAnimation, true);
+
+            //then no error was thrown
+            assertThat(true);
+        }
+
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesToWait)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/rpc/src/mx/core/Version.as b/frameworks/projects/rpc/src/mx/core/Version.as
index 463469f..158844f 100644
--- a/frameworks/projects/rpc/src/mx/core/Version.as
+++ b/frameworks/projects/rpc/src/mx/core/Version.as
@@ -22,4 +22,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as b/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
index 9d5b81d..63a0eb3 100644
--- a/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
+++ b/frameworks/projects/spark/src/spark/components/GridColumnHeaderGroup.as
@@ -782,7 +782,29 @@
     {
         return (_visibleSortIndicatorIndices.indexOf(columnIndex) != -1);
     }
-    
+
+    /**
+     *  True if either of this GridColumnHeaderGroup's views contains the global
+     *  coordinates in the event, or if they fall over this component's padding.
+     */
+    public function containsMouseEvent(event:MouseEvent):Boolean
+    {
+        return containsGlobalCoordinates(new Point(event.stageX, event.stageY));
+    }
+
+    public function containsGlobalCoordinates(coordinates:Point):Boolean
+    {
+        var globalPosition:Point = localToGlobal(new Point(getLayoutBoundsX(), getLayoutBoundsY()));
+        var bounds:Rectangle = new Rectangle(globalPosition.x, globalPosition.y, getLayoutBoundsWidth(), getLayoutBoundsHeight());
+
+        return bounds.containsPoint(coordinates);
+    }
+
+    public function areCoordinatesOverAHeaderView(coordinates:Point):Boolean
+    {
+        return getHeaderViewUnderGlobalCoordinates(coordinates) != null;
+    }
+
     //--------------------------------------------------------------------------
     //
     //  Methods 
@@ -804,28 +826,28 @@
 	 */
 	public function configureGridColumnHeaderViews():void
 	{
-        const ghl:GridHeaderLayout = layout as GridHeaderLayout;
-        if (!ghl)
+        const headerLayout:GridHeaderLayout = layout as GridHeaderLayout;
+        if (!headerLayout)
             return;
         
-		if (ghl.centerGridColumnHeaderView == null)
-			ghl.centerGridColumnHeaderView = createGridColumnHeaderView();
+		if (headerLayout.centerGridColumnHeaderView == null)
+			headerLayout.centerGridColumnHeaderView = createGridColumnHeaderView();
 		
 		if (dataGrid.lockedColumnCount > 0)
 		{
-			ghl.leftGridColumnHeaderView = createGridColumnHeaderView();
+			headerLayout.leftGridColumnHeaderView = createGridColumnHeaderView();
 		}
-		else if (ghl.leftGridColumnHeaderView)
+		else if (headerLayout.leftGridColumnHeaderView)
 		{
-			removeElement(ghl.leftGridColumnHeaderView);
-			ghl.leftGridColumnHeaderView = null;
+			removeElement(headerLayout.leftGridColumnHeaderView);
+			headerLayout.leftGridColumnHeaderView = null;
 		}
 		
 		const gridLayout:GridLayout = dataGrid.grid.layout as GridLayout;
 
-		GridHeaderViewLayout(ghl.centerGridColumnHeaderView.layout).gridView = gridLayout.centerGridView;
-		if (ghl.leftGridColumnHeaderView)
-			GridHeaderViewLayout(ghl.leftGridColumnHeaderView.layout).gridView = gridLayout.leftGridView;
+		GridHeaderViewLayout(headerLayout.centerGridColumnHeaderView.layout).gridView = gridLayout.centerGridView;
+		if (headerLayout.leftGridColumnHeaderView)
+			GridHeaderViewLayout(headerLayout.leftGridColumnHeaderView.layout).gridView = gridLayout.leftGridView;
 	}
 	
 	/**
@@ -850,7 +872,6 @@
      */
     public function getHeaderIndexAt(x:Number, y:Number):int
     {
-        // TODO: fix this: x coordinate has to be adjusted
 		const view:Group = getColumnHeaderViewAtX(x);
         return GridHeaderViewLayout(view.layout).getHeaderIndexAt(x, y);
     }
@@ -1000,16 +1021,16 @@
 	 *  comparison is based strictly on the event's location and the GridViews' bounds.
 	 *  The event's target can be anything.
 	 */
-	private function mouseEventHeaderView(event:MouseEvent):GridColumnHeaderView
+	private function getHeaderViewUnderGlobalCoordinates(globalCoordinates:Point):GridColumnHeaderView
 	{
 		const ghl:GridHeaderLayout = layout as GridHeaderLayout;
 
-		const centerGridColumnHeaderView:GridColumnHeaderView = GridColumnHeaderView(ghl.centerGridColumnHeaderView)
-		if (centerGridColumnHeaderView && centerGridColumnHeaderView.containsMouseEvent(event))
+		const centerGridColumnHeaderView:GridColumnHeaderView = GridColumnHeaderView(ghl.centerGridColumnHeaderView);
+		if (centerGridColumnHeaderView && centerGridColumnHeaderView.containsGlobalPoint(globalCoordinates))
 			return centerGridColumnHeaderView;
 		
 		const leftGridColumnHeaderView:GridColumnHeaderView = GridColumnHeaderView(ghl.leftGridColumnHeaderView);
-		if (leftGridColumnHeaderView && leftGridColumnHeaderView.containsMouseEvent(event))
+		if (leftGridColumnHeaderView && leftGridColumnHeaderView.containsGlobalPoint(globalCoordinates))
 			return leftGridColumnHeaderView;
 		
 		return null;
@@ -1018,18 +1039,18 @@
     // TODO: apologize for stashing the separatorIndex in headerCP.rowIndex
     private function eventToHeaderLocations(event:MouseEvent, headerCP:CellPosition, headerXY:Point):Boolean
     {
-        const view:Group = mouseEventHeaderView(event);
+        const stageXY:Point = new Point(event.stageX, event.stageY);
+        const view:Group = getHeaderViewUnderGlobalCoordinates(stageXY);
         if (!view)
             return false;
 
-		const stageXY:Point = new Point(event.stageX, event.stageY);
         const viewXY:Point = view.globalToLocal(stageXY);
         const viewLayout:GridHeaderViewLayout = view.layout as GridHeaderViewLayout;
         const gdv:GridDimensionsView = viewLayout.gridView.gridViewLayout.gridDimensionsView;
         const separatorIndex:int = viewLayout.getSeparatorIndexAt(viewXY.x, 0);
         
         headerCP.rowIndex = (separatorIndex != -1) ? separatorIndex + gdv.viewColumnIndex : -1;
-        headerCP.columnIndex = (separatorIndex == -1) ? viewLayout.getHeaderIndexAt(viewXY.x, 0) + gdv.viewColumnIndex : -1;
+        headerCP.columnIndex = (separatorIndex == -1) ? viewLayout.getHeaderIndexAt(viewXY.x, viewXY.y) + gdv.viewColumnIndex : -1;
         
         headerXY.x = viewXY.x + gdv.viewOriginX;
         headerXY.y = viewXY.y;
diff --git a/frameworks/projects/spark/src/spark/components/List.as b/frameworks/projects/spark/src/spark/components/List.as
index c457c5b..d122821 100644
--- a/frameworks/projects/spark/src/spark/components/List.as
+++ b/frameworks/projects/spark/src/spark/components/List.as
@@ -630,36 +630,7 @@
         super.useVirtualLayout = value;
     }
     
-    //----------------------------------
-    //  dataProvider
-    //----------------------------------
 
-    [Inspectable(category="Data")]
-    
-    /**
-     *  @private
-     *  
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    override public function set dataProvider(value:IList):void
-    {
-        // Uconditionally clear the selection, see SDK-21645.  Can't wait
-        // to commit the selection because it could be set again before
-        // commitProperties runs and that selection gets lost.
-        if (!isEmpty(_proposedSelectedIndices) || !isEmpty(selectedIndices))
-        {
-            _proposedSelectedIndices.length = 0;
-            multipleSelectionChanged = true;
-            invalidateProperties();
-            UIComponentGlobals.layoutManager.validateClient(this, true);
-        }
-        super.dataProvider = value;
-    }
-        
-        
     //--------------------------------------------------------------------------
     //
     //  Properties
diff --git a/frameworks/projects/spark/src/spark/components/Scroller.as b/frameworks/projects/spark/src/spark/components/Scroller.as
index 3ca9155..4db6528 100644
--- a/frameworks/projects/spark/src/spark/components/Scroller.as
+++ b/frameworks/projects/spark/src/spark/components/Scroller.as
@@ -759,8 +759,8 @@
     
     /**
      *  @private
-     *  These are the minimum and maximum scroll possitions allowed
-     *  for both axes.  They determine the points at which bounce and
+     *  These are the minimum and maximum scroll positions allowed
+     *  for both axes. They determine the points at which bounce and
      *  pull occur.
      */
     private var minVerticalScrollPosition:Number = 0;
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridColumnHeaderView.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridColumnHeaderView.as
index ee475ee..aecb7c2 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridColumnHeaderView.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridColumnHeaderView.as
@@ -106,8 +106,13 @@
      */
     public function containsMouseEvent(event:MouseEvent):Boolean
     {
-        const eventStageX:Number = event.stageX;
-        const eventStageY:Number = event.stageY;
+        return containsGlobalPoint(new Point(event.stageX, event.stageY));
+    }
+
+    public function containsGlobalPoint(globalCoordinates:Point):Boolean
+    {
+        const stageX:Number = globalCoordinates.x;
+        const stageY:Number = globalCoordinates.y;
         const origin:Point = localToGlobal(zeroPoint);
 
         origin.x += horizontalScrollPosition;
@@ -115,9 +120,11 @@
             origin.x -= width;
 
         origin.y += verticalScrollPosition;
-        
-        return (eventStageX >= origin.x) && (eventStageY >= origin.y) && 
-            (eventStageX < (origin.x + width)) && (eventStageY < (origin.y + height));
+
+        var headerViewContainsGlobalCoordinates:Boolean = (stageX >= origin.x) && (stageY >= origin.y) &&
+                (stageX < (origin.x + width)) && (stageY < (origin.y + height));
+
+        return headerViewContainsGlobalCoordinates;
     }   
 }
 }
\ No newline at end of file
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensions.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensions.as
index ec0a003..9c975b2 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensions.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensions.as
@@ -1183,28 +1183,31 @@
      */
     public function getColumnIndexAt(x:Number, y:Number):int
     {
-        var cur:Number = x;
+        var current:Number = x;
         var i:int;
-        
+
+        if(current < 0)
+            return -1;
+
         for (i = 0; i < _columnCount; i++)
         {
-            var temp:Number = _columnWidths[i];
+            var columnWidth:Number = _columnWidths[i];
             
             // fall back on typical widths if the actual width isn't set.
-            if (isNaN(temp))
+            if (isNaN(columnWidth))
             {
-                temp = typicalCellWidths[i];
-                if (temp == 0) // invisible column
+                columnWidth = typicalCellWidths[i];
+                if (columnWidth == 0) // invisible column
                     continue;
             }
             
             // fall back on defaultColumnWidth
-            if (isNaN(temp))
-                temp = defaultColumnWidth;
+            if (isNaN(columnWidth))
+                columnWidth = defaultColumnWidth;
             
-            cur -= temp + columnGap;
+            current -= columnWidth + columnGap;
 
-            if (cur < 0)
+            if (current < 0)
                 return i;
         }
         
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensionsView.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensionsView.as
index fe7b55a..e5444a6 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensionsView.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridDimensionsView.as
@@ -225,9 +225,9 @@
         return rowIndex >= 0 ? rowIndex : -1;
     }
     
-    public function getColumnIndexAt(viewX:Number, viewY:Number):int
+    public function getColumnIndexAt(localX:Number, localY:Number):int
     {
-        const columnIndex:int = gridDimensions.getColumnIndexAt(viewX + viewOriginX, viewY + viewOriginY) - viewColumnIndex;
+        const columnIndex:int = gridDimensions.getColumnIndexAt(localX + viewOriginX, localY + viewOriginY) - viewColumnIndex;
         return columnIndex >= 0 ? columnIndex : -1;
     }
     
diff --git a/frameworks/projects/spark/src/spark/components/gridClasses/GridHeaderViewLayout.as b/frameworks/projects/spark/src/spark/components/gridClasses/GridHeaderViewLayout.as
index 2d98b89..9432c0a 100644
--- a/frameworks/projects/spark/src/spark/components/gridClasses/GridHeaderViewLayout.as
+++ b/frameworks/projects/spark/src/spark/components/gridClasses/GridHeaderViewLayout.as
@@ -500,33 +500,25 @@
      */
     public function getHeaderIndexAt(x:Number, y:Number):int
     {
-        return gridView.gridViewLayout.gridDimensionsView.getColumnIndexAt(x, y);
-        
-        // TODO: restore the special case handling below
-        /*
-        const gridColumnHeaderGroup:GridColumnHeaderGroup = this.gridColumnHeaderGroup;
-        const grid:Grid = this.grid;
-        const columnsView:IList = this.columnsView;
-        
-        if (!gridColumnHeaderGroup || !grid || !columnsView)
-            return -1; 
-        
-        const paddingLeft:Number = gridColumnHeaderGroup.getStyle("paddingLeft");
-        const paddedX:Number = x + paddingLeft;
-        var columnIndex:int = grid.getColumnIndexAt(paddedX, 0);
-        
-        // Special case for the stretched renderer above the vertical scrollbar
-        // TODO (klin): Rethink this case if we change how the last header looks.
-        if (columnIndex < 0)
+        var headerIndex:int = -1;
+        var globalPoint:Point = gridColumnHeaderGroup.localToGlobal(new Point(x - horizontalScrollPosition, y));
+
+        if(gridColumnHeaderGroup.areCoordinatesOverAHeaderView(globalPoint))
         {
-            const contentWidth:Number = gridColumnHeaderGroup.contentWidth;
-            const totalWidth:Number = horizontalScrollPosition + gridColumnHeaderGroup.width - gridColumnHeaderGroup.getStyle("paddingRight");
-            if (paddedX >= contentWidth && paddedX < totalWidth)
-                columnIndex = grid.getPreviousVisibleColumnIndex(columnsView.length)
+            var paddingLeftStyle:Number = gridColumnHeaderGroup.getStyle("paddingLeft");
+            var paddingLeft:Number = isNaN(paddingLeftStyle) ? 0 : paddingLeftStyle;
+
+            headerIndex = gridView.gridViewLayout.gridDimensionsView.getColumnIndexAt(x - paddingLeft, y);
+
+            if(headerIndex == -1)
+            {
+                //then the point is either over the right padding, over the width of the vertical
+                //scroll bar, or over the space between the last separator and the width of the grid
+                headerIndex = grid.getPreviousVisibleColumnIndex(columnsView.length);
+            }
         }
-        
-        return columnIndex;
-        */
+
+        return headerIndex;
     }
     
     /**
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/DropDownListBase.as b/frameworks/projects/spark/src/spark/components/supportClasses/DropDownListBase.as
index aaba442..c80c2b4 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/DropDownListBase.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/DropDownListBase.as
@@ -900,7 +900,7 @@
             var proposedNewIndex:int = NO_SELECTION;
             var currentIndex:int;
                         
-            if (isDropDownOpen)
+            if (isDropDownOpen && layout)
             {   
                 // Normalize the proposed index for getNavigationDestinationIndex
                 currentIndex = userProposedSelectedIndex < NO_SELECTION ? NO_SELECTION : userProposedSelectedIndex;
@@ -992,7 +992,6 @@
         {
             event.preventDefault();
         }
-        
     }
     
     /**
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as b/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
index e700d0d..fbe1050 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as
@@ -1877,9 +1877,9 @@
         
         // We want to wait one frame after validation has occured before turning off 
         // selection transitions again.  We tried using dataGroup's updateComplete event listener, 
-        // but because some validateNows() occur (before all of the event handling code has finished), 
-        // this was occuring too early.  We also tried just using callLater or ENTER_FRAME, but that 
-        // occurs before the LayoutManager has run, so we add an ENTER_FRAME handler with a 
+        // but because some validateNow() calls occur (before all of the event handling code has
+        // finished), this was occurring too early.  We also tried just using callLater or ENTER_FRAME,
+        // but that occurs before the LayoutManager has run, so we add an ENTER_FRAME handler with a
         // low priority to make sure it occurs after the LayoutManager pass.
         systemManager.addEventListener(Event.ENTER_FRAME, allowSelectionTransitions_enterFrameHandler, false, -100);
     }
diff --git a/frameworks/projects/spark/src/spark/core/Version.as b/frameworks/projects/spark/src/spark/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/spark/src/spark/core/Version.as
+++ b/frameworks/projects/spark/src/spark/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/spark/tests/spark/components/DropDownListBase_FLEX_35362_Tests.as b/frameworks/projects/spark/tests/spark/components/DropDownListBase_FLEX_35362_Tests.as
new file mode 100644
index 0000000..1305fb2
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/DropDownListBase_FLEX_35362_Tests.as
@@ -0,0 +1,79 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+    import flash.events.KeyboardEvent;
+    import flash.ui.Keyboard;
+
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    public class DropDownListBase_FLEX_35362_Tests {
+        private var _sut:DropDownList;
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2;
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new DropDownList();
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _sut = null;
+            UIImpersonator.removeAllChildren();
+        }
+
+        [Test(async, timeout=1000)]
+        public function test_pressing_END_right_after_opening_doesnt_trigger_fatal():void
+        {
+            //given
+            UIImpersonator.addChild(_sut);
+
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_open_drop_down_and_press_key, 300);
+        }
+
+        private function then_open_drop_down_and_press_key(event:Event, passThroughData:Object):void
+        {
+            //when
+            _sut.openDropDown();
+            _sut.dispatchEvent(new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 0, Keyboard.END, 0, true, false, false, true, false));
+
+            //then - no fatal thrown
+            assertTrue(true);
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}
diff --git a/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as b/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as
new file mode 100644
index 0000000..1780240
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/List_FLEX_35306_Tests.as
@@ -0,0 +1,274 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.collections.ArrayCollection;
+    import mx.collections.IList;
+    import mx.core.mx_internal;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertFalse;
+    import org.flexunit.asserts.assertNotNull;
+    import org.flexunit.async.Async;
+    import org.flexunit.runners.Parameterized;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    import spark.skins.spark.ListSkin;
+
+    use namespace mx_internal;
+
+    [RunWith("org.flexunit.runners.Parameterized")]
+    public class List_FLEX_35306_Tests
+    {
+        private static var foo:Parameterized;
+
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 4;
+        private static var noEnterFramesRemaining:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:_ListWithMXMLBinding;
+
+        private static var _hqRedmond:_HeadquarterVO;
+        private static var _hqSantaClara:_HeadquarterVO;
+        private static var _hqBerlin:_HeadquarterVO;
+        private static var _hqMunchen:_HeadquarterVO;
+        private static var _hqNewYork:_HeadquarterVO;
+        private static var _hqSantaMaria:_HeadquarterVO;
+        private static var _hqSantaDolores:_HeadquarterVO;
+
+        [Bindable]
+        public var selectedCompany:_CompanyVO;
+        [Bindable]
+        public var potentialHeadquarters:IList;
+
+        public static var models:Array;
+        {
+            models = [[createListOfCompaniesWithOnePotentialAddressEach()], [createListOfCompaniesWithMultiplePotentialAddresses()]];
+        }
+
+        [AfterClass]
+        public static function tearDownStatic():void
+        {
+            models = null;
+        }
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new _ListWithMXMLBinding();
+            _sut.container = this;
+            _sut.setStyle("skinClass", ListSkin);
+            _sut.requireSelection = true;
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            UIImpersonator.removeAllChildren();
+            _sut = null;
+        }
+
+        [Test(order=2, async, timeout=1000, dataProvider="models", description="this should run after the main test because it rewrites the model")]
+        public function test_double_binding(companies:IList):void
+        {
+            //given
+            const firstCompany:_CompanyVO = companies.getItemAt(0) as _CompanyVO;
+            const secondCompany:_CompanyVO = companies.getItemAt(1) as _CompanyVO;
+            const secondCompanyHQ:_HeadquarterVO = secondCompany.originalHeadquarter;
+            selectedCompany = firstCompany;
+
+            UIImpersonator.addElement(_sut);
+
+            //when 1
+            selectedCompany = secondCompany;
+            potentialHeadquarters = secondCompany.potentialHeadquarters;
+
+            //then 1 - wait some frames until there's a selection
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_binding_from_bindable_var_to_list, 400, {companies:companies, expectedHQ:secondCompanyHQ});
+        }
+
+        private function then_check_binding_from_bindable_var_to_list(event:Event, passThroughData:Object):void
+        {
+            //given
+            const companies:IList = passThroughData.companies;
+            const expectedHQ:_HeadquarterVO = passThroughData.expectedHQ as _HeadquarterVO;
+            const thirdCompany:_CompanyVO = companies.getItemAt(2) as _CompanyVO;
+
+            //then
+            assertEquals("The list's selected item didn't change (correctly?) when we changed the associated bindable variable!", expectedHQ, _sut.selectedItem);
+
+            //given 2
+            var extraHQ:_HeadquarterVO = new _HeadquarterVO("hello", "address");
+
+            //when 2
+            thirdCompany.potentialHeadquarters.addItem(extraHQ);
+            potentialHeadquarters = thirdCompany.potentialHeadquarters;
+            selectedCompany = thirdCompany;
+            _sut.selectedItem = extraHQ;
+
+            //then 2 - wait some frames until there's a selection
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_binding_from_list_to_bindable_var, 400, {companies:companies, expectedHQ:extraHQ});
+        }
+
+        private function then_check_binding_from_list_to_bindable_var(event:Event, passThroughData:Object):void
+        {
+            //given
+            const companies:IList = passThroughData.companies as IList;
+            const expectedHQ:_HeadquarterVO = passThroughData.expectedHQ as _HeadquarterVO;
+
+            //then 2
+            assertEquals("The binding destination didn't change (correctly?) when we changed the list's selectedItem!", expectedHQ, selectedCompany.headquarter);
+
+            //cleanup
+            const thirdCompany:_CompanyVO = companies.getItemAt(2) as _CompanyVO;
+            thirdCompany.potentialHeadquarters.removeItem(expectedHQ);
+        }
+
+
+
+
+
+        [Test(order=1, async, timeout=1000, dataProvider="models")]
+        public function test_list_doesnt_rewrite_model(companies:IList):void
+        {
+            //given
+            const secondCompany:_CompanyVO = companies.getItemAt(1) as _CompanyVO;
+
+            //when
+            selectedCompany = secondCompany;
+            potentialHeadquarters = secondCompany.potentialHeadquarters;
+
+            UIImpersonator.addElement(_sut);
+
+            //then - wait some frames until there's a selection
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_change_dp_and_selected_item, 400, companies);
+        }
+
+        private function then_change_dp_and_selected_item(event:Event, passThroughData:Object):void
+        {
+            //given
+            const model:IList = passThroughData as IList;
+            const secondCompany:_CompanyVO = model.getItemAt(1) as _CompanyVO;
+            const thirdCompany:_CompanyVO = model.getItemAt(2) as _CompanyVO;
+
+            //then
+            assertNotNull(secondCompany.headquarter); //HUH?
+            assertEquals("The selection should be " + secondCompany.headquarter.name + "!", secondCompany.originalHeadquarter, _sut.selectedItem);
+
+            //when
+            selectedCompany = thirdCompany;
+            potentialHeadquarters = thirdCompany.potentialHeadquarters;
+
+            //then - wait some frames until the selection has changed
+            noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_check_if_model_has_been_rewritten, 400, model);
+        }
+
+        private static function then_check_if_model_has_been_rewritten(event:Event, passThroughData:Object):void
+        {
+            //given
+            const model:IList = passThroughData as IList;
+            const thirdCompany:_CompanyVO = model.getItemAt(2) as _CompanyVO;
+            const expectedHQ:_HeadquarterVO = thirdCompany.originalHeadquarter;
+
+            //then
+            assertEquals("The selection should be " + expectedHQ.name + "!", expectedHQ, _sut.selectedItem);
+
+            assertCompaniesHaveCorrectHQ(model);
+            assertNoCompanyHQWasRewritten(model);
+        }
+
+        private static function assertCompaniesHaveCorrectHQ(companiesList:IList):void
+        {
+            for each(var company:_CompanyVO in companiesList)
+            {
+                assertEquals("The headquarter of " + company.name + " has been changed to an invalid value!", company.originalHeadquarter, company.headquarter);
+            }
+        }
+
+        private static function assertNoCompanyHQWasRewritten(companiesList:IList):void
+        {
+            for each(var company:_CompanyVO in companiesList)
+            {
+                assertFalse("The headquarter of " + company.name + " has been rewritten, although with the correct value in the end", company.headquarterRewritten);
+            }
+        }
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  Set up methods
+        //
+        //--------------------------------------------------------------------------
+
+        private static function createListOfCompaniesWithMultiplePotentialAddresses():IList
+        {
+            createHeadquartersIfNeeded();
+
+            var microsoft:_CompanyVO = new _CompanyVO("Microsoft", _hqRedmond, new ArrayCollection([_hqRedmond, _hqNewYork]));
+            var intel:_CompanyVO = new _CompanyVO("Intel", _hqSantaClara, new ArrayCollection([_hqSantaClara, _hqSantaMaria, _hqSantaDolores]));
+            var wv:_CompanyVO = new _CompanyVO("VW", _hqBerlin, new ArrayCollection([_hqBerlin, _hqMunchen]));
+
+            return new ArrayCollection([microsoft, intel, wv]);
+        }
+
+        private static function createListOfCompaniesWithOnePotentialAddressEach():IList
+        {
+            createHeadquartersIfNeeded();
+
+            var microsoft:_CompanyVO = new _CompanyVO("Microsoft", _hqRedmond, new ArrayCollection([_hqRedmond]));
+            var intel:_CompanyVO = new _CompanyVO("Intel", _hqSantaClara, new ArrayCollection([_hqSantaClara]));
+            var wv:_CompanyVO = new _CompanyVO("VW", _hqBerlin, new ArrayCollection([_hqBerlin]));
+
+            return new ArrayCollection([microsoft, intel, wv]);
+        }
+
+        private static function createHeadquartersIfNeeded():void
+        {
+            if(_hqRedmond)
+                return;
+
+            _hqRedmond = new _HeadquarterVO("Redmond", "redmond address 123");
+            _hqNewYork = new _HeadquarterVO("New York", "NY address 123");
+            _hqSantaClara = new _HeadquarterVO("Santa Clara", "santa clara address 123");
+            _hqSantaMaria = new _HeadquarterVO("Santa Maria", "santa maria address 123");
+            _hqSantaDolores = new _HeadquarterVO("Santa Dolores", "santa dolores address 123");
+            _hqBerlin = new _HeadquarterVO("Berlin", "berlin address 123");
+            _hqMunchen = new _HeadquarterVO("Munchen", "munchen address 123");
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark/tests/spark/components/_CompanyVO.as b/frameworks/projects/spark/tests/spark/components/_CompanyVO.as
new file mode 100644
index 0000000..7e21808
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/_CompanyVO.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components {
+    import mx.collections.ArrayCollection;
+
+    [Bindable]
+    public class _CompanyVO
+    {
+        private var _headquarter:_HeadquarterVO;
+        private var _headquarterRewritten:Boolean = false;
+        private var _originalHeadquarter:_HeadquarterVO;
+
+        public var name:String;
+        public var potentialHeadquarters:ArrayCollection;
+
+
+        public function _CompanyVO(name:String, headquarter:_HeadquarterVO, potentialHeadquarters:ArrayCollection)
+        {
+            this.name = name;
+            this._headquarter = headquarter;
+            this._originalHeadquarter = headquarter;
+            this.potentialHeadquarters = potentialHeadquarters;
+        }
+
+        public function get headquarter():_HeadquarterVO
+        {
+            return _headquarter;
+        }
+
+        public function set headquarter(value:_HeadquarterVO):void
+        {
+            _headquarterRewritten = true;
+            _headquarter = value;
+        }
+
+        public function get headquarterRewritten():Boolean
+        {
+            return _headquarterRewritten;
+        }
+
+        public function get originalHeadquarter():_HeadquarterVO
+        {
+            return _originalHeadquarter;
+        }
+
+        public function toString():String
+        {
+            return "CompanyVO{name=" + String(name) + ", #hqs="+potentialHeadquarters.length+"}";
+        }
+    }
+}
diff --git a/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as b/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as
new file mode 100644
index 0000000..ebfeb70
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/_HeadquarterVO.as
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components {
+    [Bindable]
+    public class _HeadquarterVO {
+        public var name:String;
+        public var address:String;
+
+        public function _HeadquarterVO(name:String, address:String)
+        {
+            this.name = name;
+            this.address = address;
+        }
+
+        public function get label():String
+        {
+            return name;
+        }
+
+        public function toString():String
+        {
+            return "HeadquarterVO{name=" + String(name) + "}";
+        }
+    }
+}
diff --git a/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml b/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml
new file mode 100644
index 0000000..f2b24fb
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/_ListWithMXMLBinding.mxml
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+<?xml version="1.0"?>
+<s:List xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
+    selectedItem="@{container.selectedCompany.headquarter}"
+    dataProvider="{container.potentialHeadquarters}">
+
+    <fx:Script>
+        <![CDATA[
+        private var _container:Object;
+
+        [Bindable]
+        public function get container():Object
+        {
+            return _container;
+        }
+
+        public function set container(value:Object):void
+        {
+            _container = value;
+        }
+        ]]>
+    </fx:Script>
+</s:List>
diff --git a/frameworks/projects/spark/tests/spark/components/gridClasses/GridHeaderViewLayout_FLEX_35260_Tests.as b/frameworks/projects/spark/tests/spark/components/gridClasses/GridHeaderViewLayout_FLEX_35260_Tests.as
new file mode 100644
index 0000000..6677ea3
--- /dev/null
+++ b/frameworks/projects/spark/tests/spark/components/gridClasses/GridHeaderViewLayout_FLEX_35260_Tests.as
@@ -0,0 +1,646 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import flash.geom.Matrix;
+    import flash.geom.Point;
+    import flash.geom.Rectangle;
+
+    import mx.collections.ArrayCollection;
+
+    import org.flexunit.assertThat;
+
+    import org.flexunit.asserts.assertEquals;
+    import org.flexunit.asserts.assertTrue;
+    import org.flexunit.async.Async;
+    import org.flexunit.runners.Parameterized;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    import spark.components.DataGrid;
+    import spark.components.GridColumnHeaderGroup;
+
+    /*
+     Example for two-column table (with no horizontal scroll):
+
+     [pt]: GridColumnHeaderGroup padding top
+     [pl]: GridColumnHeaderGroup padding left
+     [lch]: still part of last column header, but beyond last column width
+
+     b0: top-left corner of the data grid. Also, first column starts at this x-coordinate
+     b1: first column ends at this x-coordinate (but the first header usually doesn't, due to [pl])
+     b2: second column ends at this x-coordinate (but the second header usually doesn't, due to [pl])
+     ...
+     bx: last column ends at this x-coordinate
+
+     c0: first column header starts at this x-coordinate
+     c1: first column header ends at this x-coordinate, separator starts at this x-coordinate, and
+         second column header (if it exists) starts at this x-coordinate + separator.width
+     c1: second column header ends at this x-coordinate, next separator (if it exists) starts at
+     this x-coordinate, and third column header (if it exists) starts at this x-coordinate + separator.width
+     ...
+     cx: last column header ends at this x-coordinate; last column separator starts at this x-coordinate
+
+     d: table ends at this x-axis coordinate
+     e: top-left corner of header. If [pt] and [pl] are 0, this coincides with b0
+     f: b0ttom-left corner of header. If [pb] and [pl] are 0, this coincides with g0
+
+     g0: header ends and grid starts at this y-coordinate
+     g1: first column ends at this x-coordinate and second column (if it exists) begins at this x-coordinate
+     g2: second column ends at this x-coordinate and third column (if it exists) begins at this x-coordinate
+     ...
+     gx: last column ends at this x-coordinate
+
+     i: bottom-right point of last column header and x-coordinate at end of data grid
+
+     And for each point we generate the 8 adjacent points:
+     (x+1, y), (x+1, y+1), (x+1, y-1),
+     (x-1, y), (x-1, y+1), (x-1, y-1),
+     (x, y-1), (x, y-1). For easier comprehension we mark them
+     using cardinal points: N, NE, E, SE, S, SW, W, NW.
+     ...and we check various boundaries against all of them
+
+     a (0, 0)
+     ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
+     ░░░░░b0═══c0══════b1═══c1════════════════════════════b2══c2═════════d░░░░░░░
+     ░░░░░║                              [pt]                            ║░░░░░░░
+     ░░░░░║    e▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓║░░░░░░░
+     ░░░░░║[pl]║▓▓▓INDEX▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓NAME▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓[lch]▓▓║░░░░░░░
+     ░░░░░║    f▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓║░░░░░░░
+     ░░░░░║                              [pb]                            ║░░░░░░░
+     ░░░░░g0═══════════g1═════════════════════════════════g2═════════════i░░░░░░░
+     ░░░░░║     01     ║     John                         ║              ║░░░░░░░
+     ░░░░░║     02     ║     Jane                         ║              ║░░░░░░░
+     ░░░░░║     03     ║     Judy                         ║              ║░░░░░░░
+     ░░░░░║     04     ║     James                        ║              ║░░░░░░░
+     ░░░░░╚════════════╩══════════════════════════════════╩══════════════╝░░░░░░░
+     ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
+     ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
+     */
+
+    [RunWith("org.flexunit.runners.Parameterized")]
+    public class GridHeaderViewLayout_FLEX_35260_Tests
+    {
+        private static var foo:Parameterized;
+        private static const N:Matrix = new Matrix(1, 0, 0, 1, 0, -1);
+        private static const NE:Matrix = new Matrix(1, 0, 0, 1, 1, -1);
+        private static const E:Matrix = new Matrix(1, 0, 0, 1, 1, 0);
+        private static const SE:Matrix = new Matrix(1, 0, 0, 1, 1, 1);
+        private static const S:Matrix = new Matrix(1, 0, 0, 1, 0, 1);
+        private static const SW:Matrix = new Matrix(1, 0, 0, 1, -1, 1);
+        private static const W:Matrix = new Matrix(1, 0, 0, 1, -1, 0);
+        private static const NW:Matrix = new Matrix(1, 0, 0, 1, -1, -1);
+        private static const ITSELF:Matrix = new Matrix(1, 0, 0, 1, 0, 0); //the point, unmodified
+        private static const directions:Array = [ITSELF, N, NE, E, SE, S, SW, W, NW];
+
+        private static const ENTIRE_HEADER_RECTANGLE:String = "visibleHeaderRectangle"; //includes padding
+        private static const FIXED_HEADER_VIEW_RECTANGLE:String = "fixedHeaderViewRectangle";
+
+        private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2;
+
+        private static var _dataGrid:DataGrid;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private var _keyRectangles:Array;
+        private var _keyPoints:Array;
+        private var _dimensions:Array;
+        private var _noEnterFramesRemaining:int = NaN;
+
+        //@TODO add cases with fixed columns
+        //@TODO can the grid itself have padding?
+        //@TODO test with a columnGap as well
+        public static var allDimensions:Array = [
+            /*x, y, width, header padding left, header padding top, header padding bottom, [column widths] */
+            [[/*x=*/    0, /*y=*/   0, /*width=*/   300, /*paddingLeft=*/   5, /*paddingTop=*/  0, /*paddingBottom=*/   0, /*columnWidths=*/[25, 150]]],
+            [[/*x=*/   10, /*y=*/   0, /*width=*/   300, /*paddingLeft=*/   5, /*paddingTop=*/  0, /*paddingBottom=*/   5, /*columnWidths=*/[25, 150]]],
+            [[/*x=*/    0, /*y=*/   0, /*width=*/   200, /*paddingLeft=*/   5, /*paddingTop=*/  0, /*paddingBottom=*/   0, /*columnWidths=*/[80, 150]]], //horizontal scroll
+            [[/*x=*/    0, /*y=*/   0, /*width=*/   100, /*paddingLeft=*/   0, /*paddingTop=*/  0, /*paddingBottom=*/   0, /*columnWidths=*/[10, 110, 15]]], //horizontal scroll
+            [[/*x=*/   -5, /*y=*/-100, /*width=*/   200, /*paddingLeft=*/  25, /*paddingTop=*/ 12, /*paddingBottom=*/   5, /*columnWidths=*/[100, 150]]] //horizontal scroll
+        ];
+
+
+        [BeforeClass]
+        public static function setUpBeforeClass():void
+        {
+            _dataGrid = new DataGrid();
+            _dataGrid.setStyle("borderVisible", false); //to not deal with the complications of Scroller.minViewportInset
+            UIImpersonator.addChild(_dataGrid);
+        }
+
+        [AfterClass]
+        public static function tearDownAfterClass():void
+        {
+            UIImpersonator.removeAllChildren();
+
+            _dataGrid = null;
+        }
+
+        [Before]
+        public function setUp():void
+        {
+
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            _keyRectangles = null;
+            _keyPoints = null;
+            _dimensions = null;
+        }
+
+
+        [Test(dataProvider="allDimensions", async, timeout=3000)]
+        public function test_ltr(dimensions:Array):void
+        {
+            //given
+            _dataGrid.width = getWidth(dimensions);
+            _dataGrid.x = getX(dimensions);
+            _dataGrid.y = getY(dimensions);
+
+            _dataGrid.columnHeaderGroup.setStyle("paddingLeft", getHeaderPaddingLeft(dimensions));
+            _dataGrid.columnHeaderGroup.setStyle("paddingTop", getHeaderPaddingTop(dimensions));
+            _dataGrid.columnHeaderGroup.setStyle("paddingBottom", getHeaderPaddingBottom(dimensions));
+
+            var gridColumns:Array = [];
+            for (var i:int = 0; i < getColumnWidths(dimensions).length; i++)
+            {
+                var column:GridColumn = new GridColumn();
+                column.width = getColumnWidth(dimensions, i);
+                gridColumns.push(column);
+            }
+            _dataGrid.columns = new ArrayCollection(gridColumns);
+
+            _dataGrid.columnHeaderGroup.invalidateDisplayList();
+            _dataGrid.columnHeaderGroup.validateNow();
+            _dataGrid.grid.validateNow();
+            _dataGrid.validateNow();
+
+            _dimensions = dimensions;
+            _keyPoints = generateKeyPoints(_dataGrid);
+            _keyRectangles = generateKeyRectangles();
+
+            _noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, doTests, 3000);
+        }
+
+        private function doTests(event:Event, passThroughData:Object):void
+        {
+            //then
+            //first, make sure that the dataGrid was rendered correctly
+            assertThat("The dataGrid has not yet been correctly rendered on stage", getActualHeaderHeight(_dataGrid) > 0);
+
+            //test the assumption about the center column header view location
+            var centerGridViewLocation:Point = GridHeaderLayout(_dataGrid.columnHeaderGroup.layout).centerGridColumnHeaderView.localToGlobal(new Point(0, 0));
+            assertTrue("The location of the centerGridColumnHeaderView does not reflect the columnHeaderGroup's padding rules! It's located at the global coordinates " +
+                    centerGridViewLocation + ", but it should be at " + _keyPoints["e"],
+                    centerGridViewLocation.equals(_keyPoints["e"]));
+
+            forEachPointAndScrollLocation(assertAssumptionsAboutPoint);
+        }
+
+        private function forEachPointAndScrollLocation(assertThat_:Function):void
+        {
+            _dataGrid.columnHeaderGroup.invalidateDisplayList();
+            _dataGrid.columnHeaderGroup.validateNow();
+            _dataGrid.grid.validateNow();
+            _dataGrid.validateNow();
+
+            var maxScroll:Number = Math.max(1, getTotalColumnWidths(_dimensions) - getWidth(_dimensions) - getHeaderPaddingLeft(_dimensions));
+            for (var i:int = 0; i < maxScroll; i++)
+            {
+                _dataGrid.grid.horizontalScrollPosition = i;
+                _dataGrid.columnHeaderGroup.invalidateDisplayList();
+                _dataGrid.columnHeaderGroup.validateNow();
+                _dataGrid.grid.validateNow();
+                _dataGrid.validateNow();
+
+                for (var pointName:String in _keyPoints)
+                {
+                    for (var j:int = 0; j < directions.length; j++)
+                    {
+                        assertThat_(getAdjacentPoint(_keyPoints[pointName], directions[j]), pointName, directions[j]);
+                        _dataGrid.columnHeaderGroup.invalidateDisplayList();
+                        _dataGrid.columnHeaderGroup.validateNow();
+                        _dataGrid.grid.validateNow();
+                        _dataGrid.validateNow();
+                    }
+                }
+            }
+        }
+
+        private function assertAssumptionsAboutPoint(point:Point, pointName:String, currentTransformation:Matrix):void
+        {
+            assertThatHeaderContainsPointOrNot(point, pointName, currentTransformation);
+            assertThatCoordinatesOverHeaderViewOrNot(point, pointName, currentTransformation);
+            assertThatHeaderIndexIsCorrect(point, pointName, currentTransformation);
+            assertThatColumnIndexIsCorrect(point, pointName, currentTransformation);
+        }
+
+        private function assertThatHeaderContainsPointOrNot(point:Point, pointName:String, currentTransformation:Matrix):void
+        {
+                    //when
+            var headerShouldContainThisPoint:Boolean = getHeaderShouldContainPointAssumption(point);
+            var doesHeaderContainThisPoint:Boolean = _sut.containsGlobalCoordinates(point);
+            const errorMessageHeaderContainsPoint:String = getHeaderContainsPointErrorMessage(pointName, currentTransformation, point, headerShouldContainThisPoint, doesHeaderContainThisPoint);
+
+            //then
+            assertEquals(errorMessageHeaderContainsPoint, headerShouldContainThisPoint, doesHeaderContainThisPoint);
+        }
+
+        private function assertThatCoordinatesOverHeaderViewOrNot(point:Point, pointName:String, currentTransformation:Matrix):void
+        {
+            //when
+            const visibleHeaderViewRectangle:Rectangle = getVisibleHeaderViewRectangle(getCurrentHScrollPosition());
+            var shouldBeContainedInMainHeaderView:Boolean = getMainHeaderViewContainsPointAssumption(visibleHeaderViewRectangle, point);
+            var shouldBeContainedInFixedHeaderView:Boolean = getFixedHeaderViewContainsPointAssumption(point);
+                    const shouldBeContainedInAHeaderView:Boolean = shouldBeContainedInMainHeaderView || shouldBeContainedInFixedHeaderView;
+            var actuallyContainedInAHeaderView:Boolean = _sut.areCoordinatesOverAHeaderView(point);
+            const errorMessageHeaderViewContainsPoint:String = getHeaderViewContainsPointErrorMessage(pointName, currentTransformation, point, shouldBeContainedInAHeaderView, actuallyContainedInAHeaderView, visibleHeaderViewRectangle);
+
+                    //then
+                    assertEquals(errorMessageHeaderViewContainsPoint, shouldBeContainedInAHeaderView, actuallyContainedInAHeaderView);
+                }
+
+        private function assertThatHeaderIndexIsCorrect(point:Point, pointName:String, currentTransformation:Matrix):void
+        {
+            //when
+            const visibleColumnHeaderRectangles:Array = getVisibleColumnHeaderRectangles(getCurrentHScrollPosition());
+            var expectedHeaderIndex:int = getHeaderIndexAssumption(point, visibleColumnHeaderRectangles);
+            var actualHeaderIndex:int = getHeaderIndexAtGlobalPoint(point);
+            const errorMessageHeaderIndex:String = getHeaderIndexErrorMessage(pointName, currentTransformation, point, expectedHeaderIndex, actualHeaderIndex, visibleColumnHeaderRectangles);
+
+            //then
+            assertEquals(errorMessageHeaderIndex, expectedHeaderIndex, actualHeaderIndex);
+        }
+
+        private function assertThatColumnIndexIsCorrect(point:Point, pointName:String, currentTransformation:Matrix):void
+        {
+            //when
+            const visibleColumnRectangles:Array = getAllColumnRectangles(getCurrentHScrollPosition());
+            var expectedColumnIndex:int = getColumnIndexAssumption(visibleColumnRectangles, point);
+            var actualColumnIndex:int = getColumnIndexAtGlobalPoint(point);
+            const errorMessageColumnIndex:String = getColumnIndexErrorMessage(pointName, currentTransformation, point, expectedColumnIndex, actualColumnIndex, visibleColumnRectangles);
+
+            //then
+            assertEquals(errorMessageColumnIndex, expectedColumnIndex, actualColumnIndex);
+        }
+
+        private function getHeaderIndexErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, expectedColumnHeaderIndex:int, actualColumnHeaderIndex:int, visibleColumnHeaderRectangles:Array):String
+        {
+            return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be "
+                    + (expectedColumnHeaderIndex == -1 ? "outside any column header bounds" : "inside the column header with index " + expectedColumnHeaderIndex)
+                    + " but was mistakenly found to be "
+                    + (actualColumnHeaderIndex == -1 ? "outside any column header bounds" : "inside the column header with index " + actualColumnHeaderIndex)
+                    + " given a horizontalScrollPosition of " + getCurrentHScrollPosition()
+                    + "\n DEBUG INFO: visibleColumnHeaderRectangles=" + visibleColumnHeaderRectangles;
+        }
+
+        private function getColumnIndexErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, expectedColumnHeaderIndex:int, actualColumnHeaderIndex:int, visibleColumnRectangles:Array):String
+        {
+            return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should have its x value "
+                    + (expectedColumnHeaderIndex == -1 ? "outside any column bounds" : "inside the column with index " + expectedColumnHeaderIndex)
+                    + " but was mistakenly found to be "
+                    + (actualColumnHeaderIndex == -1 ? "outside any column bounds" : "inside the column with index " + actualColumnHeaderIndex)
+                    + " given a horizontalScrollPosition of " + getCurrentHScrollPosition()
+                    + "\n DEBUG INFO: columnRectangles=" + visibleColumnRectangles;
+        }
+
+        private function getHeaderContainsPointErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, shouldBeContainedInHeader:Boolean, isActuallyContainedInHeader:Boolean):String
+        {
+            return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be "
+                    + (shouldBeContainedInHeader ? "within " : "outside ") + "the header bounds"
+                    + " but was mistakenly found to be "
+                    + (isActuallyContainedInHeader ? "within" : "outside")
+                    + " given a horizontalScrollPosition of " + getCurrentHScrollPosition()
+                    + "\n DEBUG INFO: header rectangle=" + entireHeaderRectangle;
+        }
+
+        private function getHeaderViewContainsPointErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, shouldBeContainedInAHeaderView:Boolean, isActuallyContainedByAHeaderView:Boolean, visibleHeaderViewRectangle:Rectangle):String
+        {
+            return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be "
+                    + (shouldBeContainedInAHeaderView ? "within " : "outside ") + "a header view"
+                    + " but was mistakenly found to be "
+                    + (isActuallyContainedByAHeaderView ? "within" : "outside")
+                    + " given a horizontalScrollPosition of " + getCurrentHScrollPosition()
+                    + "\n DEBUG INFO: rectangles of visible header views = " + fixedHeaderViewRectangle + "; " + visibleHeaderViewRectangle;
+        }
+
+        private function getHeaderIndexAtGlobalPoint(globalPoint:Point):int
+        {
+            var localPoint:Point = _sut.globalToLocal(globalPoint);
+            return _sut.getHeaderIndexAt(localPoint.x, localPoint.y);
+        }
+
+        private function getColumnIndexAtGlobalPoint(globalPoint:Point):int
+        {
+            var localPoint:Point = _dataGrid.grid.globalToLocal(globalPoint);
+            return _dataGrid.grid.getColumnIndexAt(localPoint.x, localPoint.y);
+        }
+
+        private function getHeaderShouldContainPointAssumption(point:Point):Boolean
+        {
+            return rectangleContainsPoint(entireHeaderRectangle, point);
+        }
+
+        private function getFixedHeaderViewContainsPointAssumption(point:Point):Boolean
+        {
+            return rectangleContainsPoint(fixedHeaderViewRectangle, point);
+        }
+
+        private function getMainHeaderViewContainsPointAssumption(visibleHeaderViewRectangle:Rectangle, point:Point):Boolean
+        {
+            return rectangleContainsPoint(visibleHeaderViewRectangle, point);
+        }
+
+        private function getHeaderIndexAssumption(point:Point, visibleColumnHeaderRectangles:Array):int
+        {
+            return getIndexOfRectangleWhichContainsPoint(point, visibleColumnHeaderRectangles);
+        }
+
+        private function getColumnIndexAssumption(visibleColumnRectangles:Array, point:Point):int
+        {
+            return getIndexOfRectangleWhichContainsPoint(point, visibleColumnRectangles);
+        }
+
+        private function getIndexOfRectangleWhichContainsPoint(point:Point, rectangles:Array):int
+        {
+            for (var i:int = 0; i < rectangles.length; i++)
+            {
+                if(rectangleContainsPoint(rectangles[i], point))
+                    return i;
+            }
+
+            return -1;
+        }
+
+        private function rectangleContainsPoint(rectangle:Rectangle, point:Point):Boolean
+        {
+            return rectangle.containsPoint(point);
+        }
+
+        private function getAdjacentPoint(point:Point, direction:Matrix):Point
+        {
+            return direction.transformPoint(point);
+        }
+
+        private function generateKeyPoints(grid:DataGrid):Array
+        {
+            var keyPoints:Array = [];
+
+            keyPoints["a"] = new Point(0, 0);
+            keyPoints["b0"] = new Point(getX(_dimensions), getY(_dimensions));
+            generateColumnIntermediates(keyPoints, _dimensions, "b0");
+            keyPoints["c0"] = new Point(getX(_dimensions) + getHeaderPaddingLeft(_dimensions), getY(_dimensions));
+            generateColumnIntermediates(keyPoints, _dimensions, "c0");
+            keyPoints["d"] = new Point(getX(_dimensions) + getWidth(_dimensions), getY(_dimensions));
+            keyPoints["e"] = new Point(Point(keyPoints["c0"]).x, getY(_dimensions) + getHeaderPaddingTop(_dimensions));
+            keyPoints["f"] = new Point(Point(keyPoints["c0"]).x, getY(_dimensions) + getActualHeaderHeight(grid) - getHeaderPaddingBottom(_dimensions));
+            keyPoints["g0"] = new Point(getX(_dimensions), getY(_dimensions) + getActualHeaderHeight(grid));
+            generateColumnIntermediates(keyPoints, _dimensions, "g0");
+            keyPoints["i"] = new Point(getX(_dimensions) + getWidth(_dimensions), Point(keyPoints["g0"]).y);
+            return keyPoints;
+        }
+
+        private function generateColumnIntermediates(keyPoints:Array, dimensions:Array, initialPointName:String):void
+        {
+            const initialPoint:Point = keyPoints[initialPointName];
+            const y:Number = initialPoint.y;
+            var currentX:Number = initialPoint.x;
+            const initialPointFirstCharacter:String = initialPointName.charAt(0);
+            for (var i:int = 0; i < getColumnWidths(dimensions).length; i++)
+            {
+                currentX += getColumnWidth(dimensions, i);
+                keyPoints[initialPointFirstCharacter + (i+1)] = new Point(currentX, y);
+            }
+        }
+
+        private function generateKeyRectangles():Array
+        {
+            var keyRectangles:Array = [];
+
+            keyRectangles[ENTIRE_HEADER_RECTANGLE] = generateVisibleHeaderRectangle();
+            keyRectangles[FIXED_HEADER_VIEW_RECTANGLE] = generateFixedHeaderViewRectangle();
+
+            return keyRectangles;
+        }
+
+        private function generateFixedHeaderViewRectangle():Rectangle
+        {
+            //this is the GridColumnHeaderGroup.centerGridColumnHeaderView, which is holds the non-fixed columns; padding excluded
+            const topLeftCorner:Point = _keyPoints["e"];
+            return new Rectangle(topLeftCorner.x, topLeftCorner.y, 0, 0);
+        }
+
+        private function generateVisibleHeaderRectangle():Rectangle
+        {
+            const topLeftCorner:Point = _keyPoints["b0"];
+            const bottomRightCorner:Point = _keyPoints["i"];
+            return new Rectangle(topLeftCorner.x, topLeftCorner.y, bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - topLeftCorner.y);
+        }
+
+
+        private function getActualHeaderHeight(grid:DataGrid):Number
+        {
+            //Note that we're assuming the grid is on stage and validated by this point!
+            return grid.columnHeaderGroup.height;
+        }
+
+        private function getCurrentHScrollPosition():Number
+        {
+            return _dataGrid.grid.horizontalScrollPosition;
+        }
+
+
+        private function getVisibleHeaderViewRectangle(hScrollPosition:Number = 0):Rectangle
+        {
+            //this is the GridColumnHeaderGroup.centerGridColumnHeaderView, which holds the non-fixed columns; padding excluded
+            const topLeftCorner:Point = _keyPoints["e"];
+            return new Rectangle(topLeftCorner.x, topLeftCorner.y,
+                    getHeaderWidthFromKeyPoints(_keyPoints) - getHeaderPaddingLeft(_dimensions),
+                    getHeaderHeightFromKeyPoints(_keyPoints) - getHeaderPaddingTop(_dimensions) - getHeaderPaddingBottom(_dimensions));
+        }
+
+        private function getVisibleColumnHeaderRectangles(hScrollPosition:Number = 0):Array
+        {
+            var headerRectangles:Array = [];
+
+            const headerPaddingTop:Number = getHeaderPaddingTop(_dimensions);
+            const headerPaddingBottom:Number = getHeaderPaddingBottom(_dimensions);
+            const headerHeight:Number = getHeaderHeightFromKeyPoints(_keyPoints) - headerPaddingTop - headerPaddingBottom;
+            const numColumns:uint = getColumnWidths(_dimensions).length;
+            const headerPaddingLeft:Number = getHeaderPaddingLeft(_dimensions);
+            const headerWidth:Number = getWidth(_dimensions) - headerPaddingLeft;
+            const e:Point = _keyPoints["e"];
+            const visibleRectangle:Rectangle = new Rectangle(e.x, e.y, headerWidth, 100);
+            var totalColumnWidths:Number = getTotalColumnWidths(_dimensions);
+            var columnHeaderY:Number = NaN;
+
+            //create the header rectangles from the first visible point on the left until the end
+            for (var i:int = 0; i < numColumns; i++)
+            {
+                var topLeft:Point = _keyPoints["c" + i];
+                var topRight:Point = _keyPoints["c" + (i+1)];
+                var topLeftX:Number = topLeft.x - hScrollPosition;
+                var topRightX:Number = topRight.x - hScrollPosition;
+
+                if(isNaN(columnHeaderY))
+                    columnHeaderY = topLeft.y + headerPaddingTop;
+
+                var endsBeforeVisibleRectangle:Boolean = topRightX < visibleRectangle.x;
+                var startsAfterVisibleRectangle:Boolean = topLeftX >= visibleRectangle.x + visibleRectangle.width;
+
+                if(!(endsBeforeVisibleRectangle || startsAfterVisibleRectangle))
+                {
+                    const startingX:Number = Math.max(topLeftX, visibleRectangle.x);
+                    const rightEdge:Number = Math.min(topRightX, visibleRectangle.x + visibleRectangle.width);
+                    const width:Number = rightEdge - startingX;
+                    headerRectangles.push(new Rectangle(startingX, columnHeaderY, width, headerHeight));
+                }
+            }
+
+            assertThat("no example has 0 columns, so we expect this Array to have at least one item.", headerRectangles.length > 0);
+
+            //correct last header rectangle to extend to grid boundaries if the total width of all the columns is smaller
+            //than the grid's width. It is one of the issues which prompted this unit test in the first place.
+            if(totalColumnWidths <= headerWidth)
+            {
+                var lastHeaderRectangle:Rectangle = headerRectangles[headerRectangles.length - 1];
+                lastHeaderRectangle.width = Point(_keyPoints["d"]).x - lastHeaderRectangle.x;
+            }
+
+            return headerRectangles;
+        }
+
+
+        //Note that the height and y of the rectangles needs to be all-encompassing until FLEX-35280 is fixed
+        private function getAllColumnRectangles(hScrollPosition:Number = 0):Array
+        {
+            var columnRectangles:Array = [];
+            const numColumns:uint = getColumnWidths(_dimensions).length;
+
+            for (var i:int = 0; i < numColumns; i++)
+            {
+                var topLeft:Point = _keyPoints["g" + i];
+                var topRight:Point = _keyPoints["g" + (i+1)];
+
+                columnRectangles.push(new Rectangle(topLeft.x, -10000, topRight.x - topLeft.x, Number.MAX_VALUE));
+            }
+
+            return columnRectangles;
+        }
+
+        /* key rectangles getters */
+
+        private function get entireHeaderRectangle():Rectangle //includes padding
+        {
+            return _keyRectangles[ENTIRE_HEADER_RECTANGLE] as Rectangle;
+        }
+
+        private function get fixedHeaderViewRectangle():Rectangle
+        {
+            return _keyRectangles[FIXED_HEADER_VIEW_RECTANGLE] as Rectangle;
+        }
+
+        /* key points getters */
+
+        private function getColumnWidthFromKeyPoints(keyPoints:Array, columnIndex:int):Number
+        {
+            //we're assuming columnIndex has a valid value
+            return Point(keyPoints["c" + (columnIndex + 1)]).x - Point(keyPoints["c" + columnIndex]).x;
+        }
+
+        private function getHeaderHeightFromKeyPoints(keyPoints:Array):Number
+        {
+            return Point(keyPoints["i"]).y - Point(keyPoints["d"]).y;
+        }
+
+        private function getHeaderWidthFromKeyPoints(keyPoints:Array):Number
+        {
+            return Point(keyPoints["d"]).x - Point(keyPoints["b0"]).x;
+        }
+
+        /* dimensions getters */
+
+        private function getX(dimensions:Array):Number
+        {
+            return dimensions[0];
+        }
+
+        private function getY(dimensions:Array):Number
+        {
+            return dimensions[1];
+        }
+
+        private function getWidth(dimensions:Array):Number
+        {
+            return dimensions[2];
+        }
+
+        private function getHeaderPaddingLeft(dimensions:Array):Number
+        {
+            return dimensions[3];
+        }
+
+        private function getHeaderPaddingTop(dimensions:Array):Number
+        {
+            return dimensions[4];
+        }
+
+        private function getHeaderPaddingBottom(dimensions:Array):Number
+        {
+            return dimensions[5];
+        }
+
+        private function getColumnWidths(dimensions:Array):Array
+        {
+            return dimensions[6];
+        }
+
+        private function getColumnWidth(dimensions:Array, columnIndex:int):Number
+        {
+            return getColumnWidths(dimensions)[columnIndex];
+        }
+
+        private function getTotalColumnWidths(dimensions:Array):Number
+        {
+            var sum:Number = 0;
+            getColumnWidths(dimensions).forEach(function (item:*, index:int, arr:Array):void {sum += item;});
+            return sum;
+        }
+
+
+        private function onEnterFrame(event:Event):void
+        {
+            if(!--_noEnterFramesRemaining)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+
+        private function get _sut():GridColumnHeaderGroup
+        {
+            return _dataGrid.columnHeaderGroup;
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/spark_dmv/src/spark/core/Version.as b/frameworks/projects/spark_dmv/src/spark/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/spark_dmv/src/spark/core/Version.as
+++ b/frameworks/projects/spark_dmv/src/spark/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/tool/src/mx/core/Version.as b/frameworks/projects/tool/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/tool/src/mx/core/Version.as
+++ b/frameworks/projects/tool/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/frameworks/projects/tool_air/src/mx/core/Version.as b/frameworks/projects/tool_air/src/mx/core/Version.as
index 3077bda..9cc2191 100644
--- a/frameworks/projects/tool_air/src/mx/core/Version.as
+++ b/frameworks/projects/tool_air/src/mx/core/Version.as
@@ -23,4 +23,4 @@
  *  @private
  *  Version string for this class.
  */
-mx_internal static const VERSION:String = "4.16.0.0";
+mx_internal static const VERSION:String = "4.16.1.0";
diff --git a/installer.xml b/installer.xml
index 5996861..ef08ef2 100644
--- a/installer.xml
+++ b/installer.xml
@@ -351,7 +351,7 @@
         <antcall target="air-get" />

 

         <antcall target="air-setup-win" />

-        <antcall target="air-setup-mac" />

+		<antcall target="air-setup-mac-init" />

         

     </target>

 

@@ -377,7 +377,7 @@
             <param name="md5" value="${air.sdk.url.md5}" />

         </antcall>

     </target>

-    

+	

     <target name="air-setup-win" if="isWindows">

         <unzip src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />

         <echo>${INFO_FINISHED_UNZIPPING} ${download.dir}/${air.sdk.url.file}</echo>

@@ -419,9 +419,8 @@
     	<echo message="Should unzip: ${shouldUnzip}"/>

     </target>

 

-    <target name="unzipAIRSDK" if="${shouldUnzip}">

+	<target name="unzipAIRSDK" if="${shouldUnzip}">

     	<echo message="Unzipping"/>

-

     	<!--The tbz2 contains symlinks which Ant does not preserve

         <untar compression="bzip2" src="${download.dir}/${air.sdk.url.file}" dest="${download.dir}/airsdk" />-->

         

@@ -441,6 +440,7 @@
     

 	<target name="mountAIRSDK" unless="${shouldUnzip}">

 		<echo message="Mounting dmg"/>

+		<echo message="IS WINDOWS: ${isWindows}, IS MAC: ${isMac}" />

 		<exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">

 	      <arg value="attach"/>

 	      <arg value="-nobrowse"/>

@@ -448,7 +448,7 @@
 	    </exec>

 	</target>

 

-	<target name="copyFromMount" unless="${shouldUnzip}">

+	<target name="copyFromMount" unless="${shouldUnzip}">
 		<echo message="Copying AIR SDK from mounted volume"/>

 		<exec executable="rsync" dir="${FLEX_HOME}">

             <arg value="--archive" />

@@ -459,7 +459,7 @@
         </exec>

 	</target>

 

-	<target name="unmountAIRSDK" unless="${shouldUnzip}">

+	<target name="unmountAIRSDK" unless="${shouldUnzip}">
 		<echo message="Unmounting AIR SDK"/>

 		<exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="false">

 	      <arg value="unmount"/>

@@ -467,7 +467,11 @@
 	    </exec>

 	</target>

     

-    <target name="air-setup-mac" depends="unzipOrMountDMG,unzipAIRSDK,mountAIRSDK,copyFromMount,unmountAIRSDK" unless="isWindows">

+	<target name="air-setup-mac-init" unless="isWindows">

+		<antcall target="air-setup-mac" />

+	</target>

+	

+	<target name="air-setup-mac" depends="unzipOrMountDMG,unzipAIRSDK,mountAIRSDK,copyFromMount,unmountAIRSDK">
         <antcall target="mac-copy-file">

             <param name="srcdir" value="." />

             <param name="filename" value="AIR SDK license.pdf"/>

diff --git a/modules/asc/src/java/macromedia/asc/embedding/LintEvaluator.java b/modules/asc/src/java/macromedia/asc/embedding/LintEvaluator.java
index de2ea96..359af64 100644
--- a/modules/asc/src/java/macromedia/asc/embedding/LintEvaluator.java
+++ b/modules/asc/src/java/macromedia/asc/embedding/LintEvaluator.java
@@ -749,8 +749,14 @@
 			boolean is_unbound_ref       = is_unbound_dotref || is_unbound_lexref || is_unbound_globalref;
 
 
-			if (slot != null )
+			if (slot != null && !(node.expr instanceof QualifiedIdentifierNode))
+			{
+				//if it's a qualified identifier node, then it's a member/static
+				//variable on a class that is being initialized, like this:
+				//public var memberVar:String = "hi";
+				//this case should not have a warning!
 				checkDeprecatedSlot(cx, node.expr, node.ref, slot);
+			}
 			
 			// special case to avoid warning on access to a Class's prototype property.  This
 			//  property can't be expressed in global.as because you can't both declare a class
diff --git a/modules/compiler/src/java/flex2/compiler/common/MxmlConfiguration.java b/modules/compiler/src/java/flex2/compiler/common/MxmlConfiguration.java
index 08a9c0c..1614611 100644
--- a/modules/compiler/src/java/flex2/compiler/common/MxmlConfiguration.java
+++ b/modules/compiler/src/java/flex2/compiler/common/MxmlConfiguration.java
@@ -46,6 +46,8 @@
     //
     // 'compiler.mxml.compatibility-version' option
     //
+	public static final int VERSION_4_16_1 = 0x04100001;
+	public static final int VERSION_4_16 = 0x04100000;
     public static final int VERSION_4_15 = 0x040f0000;
     public static final int VERSION_4_14_1 = 0x040e0001;
 	public static final int VERSION_4_14 = 0x040e0000;
@@ -63,10 +65,10 @@
     public static final int VERSION_3_0 = 0x03000000;
     public static final int VERSION_2_0_1 = 0x02000001;
     public static final int VERSION_2_0 = 0x02000000;
-    public static final int CURRENT_VERSION = VERSION_4_15;
+    public static final int CURRENT_VERSION = VERSION_4_16_1;
     public static final int EARLIEST_MAJOR_VERSION = 3;
     public static final int LATEST_MAJOR_VERSION = 4;
-    public static final int LATEST_MINOR_VERSION = 15;
+    public static final int LATEST_MINOR_VERSION = 16;
 
 	private int major = LATEST_MAJOR_VERSION;
 	private int minor = LATEST_MINOR_VERSION;
diff --git a/modules/compiler/src/java/flex2/tools/VersionInfo.java b/modules/compiler/src/java/flex2/tools/VersionInfo.java
index 6e740cc..4ded09c 100644
--- a/modules/compiler/src/java/flex2/tools/VersionInfo.java
+++ b/modules/compiler/src/java/flex2/tools/VersionInfo.java
@@ -33,7 +33,7 @@
 {
     public static String FLEX_MAJOR_VERSION = "4";
     public static String FLEX_MINOR_VERSION = "16";
-    public static String FLEX_NANO_VERSION  = "0";
+    public static String FLEX_NANO_VERSION  = "1";
     
 	/**
 	 * Lib version is the "version" of the SWC format. Major number changes represent big (although not
diff --git a/releasecandidate.xml b/releasecandidate.xml
index 7597846..c2d43f8 100644
--- a/releasecandidate.xml
+++ b/releasecandidate.xml
@@ -49,9 +49,10 @@
     </condition>
 	
 	<property name="rat.report" value="${basedir}/rat-report.txt"/>
-	<property name="apache.rat.jar" value="apache-rat-0.8.jar" />
-	<property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.8.jar" />
-	<property name="apache.rat.url" value="http://people.apache.org/~aharui/rat" />
+	<property name="apache.rat.jar" value="apache-rat-0.11.jar" />
+	<property name="apache.rat.tasks.jar" value="apache-rat-tasks-0.11.jar" />
+	<property name="apache.rat.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat/0.11" />
+	<property name="apache.rat.tasks.url" value="http://search.maven.org/remotecontent?filepath=org/apache/rat/apache-rat-tasks/0.11"/>
     
 	<property file="${basedir}/local.properties" />
 	<property file="${basedir}/build.properties" />
@@ -192,7 +193,7 @@
 		<get src="${apache.rat.url}/${apache.rat.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.jar}" />
 	</target>
 	<target name="install-rat.tasks.jar" unless="apache.rat.tasks.found">
-		<get src="${apache.rat.url}/${apache.rat.tasks.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.tasks.jar}" />
+		<get src="${apache.rat.tasks.url}/${apache.rat.tasks.jar}" dest="${env.ANT_HOME}/lib/${apache.rat.tasks.jar}" />
 	</target>
 	
     <target name="rat-taskdef" description="Rat taskdef">