Repository: flex-sdk Updated Branches: refs/heads/develop 98c9446c1 -> 5df1f00a7
FLEX-33311 CAUSE: It is possible for a call to ConstraintLayout.parseElementConstraints() to trigger, after a long series of other functions, a validation cycle on the same component whose layout is that ConstraintLayout instance. (If you want to see that series of stack traces, open stack.xml on the Jira ticket.) When this happens, either ConstraintLayout.measure() or ConstraintLayout.updateDisplayList() ends up calling clearConstraintCache(). (This is expected behaviour when there's no convoluted stack trace which ends up re-validating the same component, as we have here.) Now, when this inner validation cycle ends, and the outer call to parseConstraints() continues execution, it does so with all the cache variables nulled. This can result in a fatal if there is still a layout element remaining in parseConstraints() to parse via parseElementConstraints(). The latter function needs the cache Vector "rowBaselines", which is now null. SOLUTION: To cater for the special case when the call to parseConstraints() triggers another call to the same function, on the same ConstraintLayout instance, we use a counter to know when we're back in the outer call (when the counter is 0). NOTES: -The unit test now passes. -Also removed an unused local variable. Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/5df1f00a Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/5df1f00a Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/5df1f00a Branch: refs/heads/develop Commit: 5df1f00a71319c4aa6471128dab5e918e01334f0 Parents: 98c9446 Author: Mihai Chira <[email protected]> Authored: Wed Aug 17 18:44:22 2016 +0200 Committer: Mihai Chira <[email protected]> Committed: Wed Aug 17 18:44:22 2016 +0200 ---------------------------------------------------------------------- .../spark/src/spark/layouts/ConstraintLayout.as | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/5df1f00a/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as b/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as index 4953917..d698103 100644 --- a/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as +++ b/frameworks/projects/spark/src/spark/layouts/ConstraintLayout.as @@ -121,6 +121,10 @@ use namespace mx_internal; */ public class ConstraintLayout extends LayoutBase { + + //See FLEX-33311 for more details on why this is used + private var constraintCacheNeeded:int = 0; + //-------------------------------------------------------------------------- // // Class methods @@ -1604,7 +1608,9 @@ public class ConstraintLayout extends LayoutBase var layoutTarget:GroupBase = target; if (!layoutTarget) return; - + + constraintCacheNeeded++; + var count:Number = layoutTarget.numElements; var layoutElement:ILayoutElement; @@ -1614,7 +1620,7 @@ public class ConstraintLayout extends LayoutBase // Populate rowBaselines with baseline information from rows. var n:int = _constraintRows.length; var row:ConstraintRow; - var obj:Object = {}; + if (rowBaselines == null) rowBaselines = new Vector.<Array>(); else @@ -1641,6 +1647,7 @@ public class ConstraintLayout extends LayoutBase } this.constraintCache = cache; + constraintCacheNeeded--; } /** @@ -1833,12 +1840,15 @@ public class ConstraintLayout extends LayoutBase */ private function clearConstraintCache():void { - colSpanElements = null; - rowSpanElements = null; - otherElements = null; - rowBaselines = null; - rowMaxAscents = null; - constraintCache = null; + if(!constraintCacheNeeded) + { + colSpanElements = null; + rowSpanElements = null; + otherElements = null; + rowBaselines = null; + rowMaxAscents = null; + constraintCache = null; + } } } }
