This is an automated email from the ASF dual-hosted git repository. gregdove pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit acab343f73b939bb3b28a13f9142cba4f799104a Author: greg-dove <greg.d...@gmail.com> AuthorDate: Wed Apr 6 13:41:58 2022 +1200 Avoid the possibility of infinite loops (in JS only, SWF untested) with xml watchers. This can happen if changes are made in watcher functions. --- .../src/main/royale/mx/utils/XMLNotifier.as | 71 ++++++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/XMLNotifier.as b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/XMLNotifier.as index 5bc8a13fa1..c4d033b476 100644 --- a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/XMLNotifier.as +++ b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/XMLNotifier.as @@ -20,10 +20,14 @@ package mx.utils { -import org.apache.royale.utils.ObjectMap; +//import org.apache.royale.utils.ObjectMap; import mx.core.mx_internal; import mx.utils.IXMLNotifiable; +COMPILE::SWF{ + import flash.utils.Dictionary; +} + use namespace mx_internal; /** @@ -98,13 +102,32 @@ public class XMLNotifier { callee = notificationFunction; } - var xmlWatchers:ObjectMap = callee["watched"]; - if (xmlWatchers != null) - { - xmlWatchers.forEach( function(truevalue:Object,notifiable:Object,map:Object):void { + //var xmlWatchers:ObjectMap = callee["watched"]; + + COMPILE::SWF{ + var xmlWatchers:Dictionary = callee["watched"]; + for (var notifiable:Object in xmlWatchers) { IXMLNotifiable(notifiable).xmlNotification(currentTarget, ty, tar, value, detail); - } ); + } } + + COMPILE::JS{ + var xmlWatchers:Map = callee["watched"]; + if (xmlWatchers != null) + { + var collected:Array = []; + //note, if we don't collect these first and try to iterate directly, then there can be the case that iterating is infinite if the function caLL also somehow affects the xmlWatchers Map: + xmlWatchers.forEach( function(truevalue:Object,notifiable:Object,map:Object):void { + collected.push(notifiable); + } ); + + while(collected.length){ + IXMLNotifiable(collected.shift()).xmlNotification(currentTarget, ty, tar, value, detail); + } + } + } + + } return notificationFunction; @@ -181,13 +204,25 @@ public class XMLNotifier } // Watch lists are maintained on the notification function. - var xmlWatchers:ObjectMap; - if (watcherFunction["watched"] == undefined) - watcherFunction["watched"] = xmlWatchers = new ObjectMap(true,true); + if (watcherFunction["watched"] == undefined) { + // watcherFunction["watched"] = xmlWatchers = new ObjectMap(true,true); + COMPILE::SWF{ + var xmlWatchers:Dictionary = watcherFunction["watched"] = new Dictionary(); + } + + COMPILE::JS{ + var xmlWatchers:Map= watcherFunction["watched"] = new Map(); + } + } else xmlWatchers = watcherFunction["watched"]; - xmlWatchers.set(notifiable, true); + COMPILE::SWF{ + xmlWatchers[notifiable]=true; + } + COMPILE::JS{ + xmlWatchers.set(notifiable, true); + } } } @@ -223,12 +258,24 @@ public class XMLNotifier if (!(watcherFunction is Function)) return; - var xmlWatchers:ObjectMap; + COMPILE::SWF{ + var xmlWatchers:Dictionary; + } + + COMPILE::JS{ + var xmlWatchers:Map; + } if (watcherFunction["watched"] != undefined) { xmlWatchers = watcherFunction["watched"]; - xmlWatchers.delete(notifiable); + COMPILE::SWF{ + delete xmlWatchers[notifiable]; + } + COMPILE::JS{ + xmlWatchers.delete(notifiable); + } + } } }