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 ed645b9806e82dcd43722d4640c95e41798d545f Author: greg-dove <[email protected]> AuthorDate: Fri Apr 24 17:47:51 2020 +1200 Ported support for ChangeWatcher.watch (without weakReference) --- .../src/main/royale/mx/binding/BindabilityInfo.as | 179 +++++++++++++++------ .../main/royale/mx/binding/utils/ChangeWatcher.as | 56 +++---- 2 files changed, 161 insertions(+), 74 deletions(-) diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/binding/BindabilityInfo.as b/frameworks/projects/MXRoyale/src/main/royale/mx/binding/BindabilityInfo.as index 8500fbe..ede40bf 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/mx/binding/BindabilityInfo.as +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/binding/BindabilityInfo.as @@ -20,8 +20,22 @@ package mx.binding { +COMPILE::SWF{ + import flash.utils.Dictionary; +} + import mx.events.PropertyChangeEvent; + +import org.apache.royale.events.ValueChangeEvent; +import org.apache.royale.reflection.DefinitionWithMetaData; +import org.apache.royale.reflection.MetaDataArgDefinition; +import org.apache.royale.reflection.MetaDataDefinition; +import org.apache.royale.reflection.TypeDefinition; +import org.apache.royale.reflection.describeType; +import org.apache.royale.reflection.utils.getMembersWithNameMatch; +import org.apache.royale.reflection.utils.filterForMetaTags; + [ExcludeClass] /** @@ -38,7 +52,7 @@ public class BindabilityInfo // Class constants // //-------------------------------------------------------------------------- - + /** * Name of [Bindable] metadata. * @@ -57,7 +71,7 @@ public class BindabilityInfo * @playerversion AIR 1.1 * @productversion Flex 3 */ - public static const MANAGED:String = "Managed"; +// public static const MANAGED:String = "Managed"; /** * Name of [ChangeEvent] metadata. @@ -67,7 +81,7 @@ public class BindabilityInfo * @playerversion AIR 1.1 * @productversion Flex 3 */ - public static const CHANGE_EVENT:String = "ChangeEvent"; +// public static const CHANGE_EVENT:String = "ChangeEvent"; /** * Name of [NonCommittingChangeEvent] metadata. @@ -77,8 +91,8 @@ public class BindabilityInfo * @playerversion AIR 1.1 * @productversion Flex 3 */ - public static const NON_COMMITTING_CHANGE_EVENT:String = - "NonCommittingChangeEvent"; + //public static const NON_COMMITTING_CHANGE_EVENT:String = + // "NonCommittingChangeEvent"; /** * Name of describeType() <accessor> element. @@ -100,6 +114,50 @@ public class BindabilityInfo */ public static const METHOD:String = "method"; + + COMPILE::SWF + private static const cache:Dictionary = new Dictionary(); + + COMPILE::JS + private static const cache:Map = new Map() + + //-------------------------------------------------------------------------- + // + // Static methods + // + //-------------------------------------------------------------------------- + + public static function getCachedInfo(forTarget:Object):BindabilityInfo{ + var typeDef:TypeDefinition = describeType(forTarget); + var info:BindabilityInfo = getFromCache(typeDef); + if (!info) { + info = new BindabilityInfo(typeDef, true); + } + return info; + } + + private static function getFromCache(typeDef:TypeDefinition):BindabilityInfo{ + var info:BindabilityInfo; + COMPILE::SWF{ + info = cache[typeDef.getClass()] + } + COMPILE::JS{ + info = cache.get(typeDef.getClass()) + } + return info; + } + + private static function storeInCache(info:BindabilityInfo):void{ + var typeDef:TypeDefinition = info.typeDefinition; + COMPILE::SWF{ + cache[typeDef.getClass()] = info; + } + COMPILE::JS{ + cache.set(typeDef.getClass(), info); + } + } + + //-------------------------------------------------------------------------- // // Constructor @@ -114,11 +172,14 @@ public class BindabilityInfo * @playerversion AIR 1.1 * @productversion Flex 3 */ - public function BindabilityInfo(typeDescription:XML) + public function BindabilityInfo(typeDefinition:TypeDefinition, cache:Boolean=false) { super(); - this.typeDescription = typeDescription; + this.typeDefinition = typeDefinition; + if (cache) { + storeInCache(this); + } } //-------------------------------------------------------------------------- @@ -130,7 +191,7 @@ public class BindabilityInfo /** * @private */ - private var typeDescription:XML; + private var typeDefinition:TypeDefinition; /** * @private @@ -168,33 +229,29 @@ public class BindabilityInfo // Seed with class-level events. changeEvents = copyProps(getClassChangeEvents(), {}); - // Get child-specific events. - var childDesc:XMLList = - typeDescription.accessor.(@name == childName) + - typeDescription.method.(@name == childName); - - var numChildren:int = childDesc.length(); + var accessorsAndMethods:Array = []; + + getMembersWithNameMatch(typeDefinition.accessors, childName, accessorsAndMethods); + getMembersWithNameMatch(typeDefinition.methods, childName, accessorsAndMethods); + + var numChildren:int = accessorsAndMethods.length; if (numChildren == 0) { - // we've been asked for events on an unknown property - if (!typeDescription.@dynamic) - { - trace("warning: no describeType entry for '" + - childName + "' on non-dynamic type '" + - typeDescription.@name + "'"); - } + trace("warning: no describeType entry for '" + + childName + "' on non-dynamic type '" + + typeDefinition.name + "'"); } else { if (numChildren > 1) { trace("warning: multiple describeType entries for '" + - childName + "' on type '" + typeDescription.@name + - "':\n" + childDesc); + childName + "' on type '" + typeDefinition.name + + "':\n" + accessorsAndMethods); } - addBindabilityEvents(childDesc.metadata, changeEvents); + addBindabilityEvents(accessorsAndMethods, changeEvents); } childChangeEvents[childName] = changeEvents; @@ -207,35 +264,45 @@ public class BindabilityInfo * @private * Build or return cached class change events object. */ + private function getClassChangeEvents():Object { if (!classChangeEvents) { classChangeEvents = {}; - addBindabilityEvents(typeDescription.metadata, classChangeEvents); + //@todo check this (currently fails in swf at runtime) + //addBindabilityEvents(typeDefinition.metadata, classChangeEvents); + + //if class has Bindable metadata, assume yes ? + if (typeDefinition.retrieveMetaDataByName('Bindable').length) { + classChangeEvents[ValueChangeEvent.VALUE_CHANGE] = true; + } + // tbd, do we want this? // Class-level [Managed] means all properties - // dispatch propertyChange. - if (typeDescription.metadata.(@name == MANAGED).length() > 0) - { - classChangeEvents[PropertyChangeEvent.PROPERTY_CHANGE] = true; + // dispatch valueChange. + if (typeDefinition.retrieveMetaDataByName('Managed').length) { + classChangeEvents[ValueChangeEvent.VALUE_CHANGE] = true; } + } return classChangeEvents; } + /** * @private */ - private function addBindabilityEvents(metadata:XMLList, + + private function addBindabilityEvents(members:Array, eventListObj:Object):void { - addChangeEvents(metadata.(@name == BINDABLE), eventListObj, true); - addChangeEvents(metadata.(@name == CHANGE_EVENT), eventListObj, true); - addChangeEvents(metadata.(@name == NON_COMMITTING_CHANGE_EVENT), - eventListObj, false); + var metaNames:Array = [BINDABLE]; + var changeEvents:Array = filterForMetaTags(members, metaNames); + + addChangeEvents(changeEvents, eventListObj ); } /** @@ -244,20 +311,40 @@ public class BindabilityInfo * to an event list object. * Note: metadata's first arg value is assumed to be change event name. */ - private function addChangeEvents(metadata:XMLList, eventListObj:Object, isCommit:Boolean):void + + private function addChangeEvents(members:Array, eventListObj:Object):void { - for each (var md:XML in metadata) + for each (var md:DefinitionWithMetaData in members) { - var arg:XMLList = md.arg; - if (arg.length() > 0) - { - var eventName:String = arg[0].@value; - eventListObj[eventName] = isCommit; - } - else - { - trace("warning: unconverted Bindable metadata in class '" + - typeDescription.@name + "'"); + var metaNames:Array = [BINDABLE]; + + for each(var meta:String in metaNames) { + var metaItems:Array = md.retrieveMetaDataByName(meta); + if (metaItems.length) { + //if there is no arg, then it is valueChange + for each(var metaItem:MetaDataDefinition in metaItems) { + if (metaItem.args.length) { + //check for no key + var eventTypeArgs:Array = metaItem.getArgsByKey(''); + if (!eventTypeArgs.length) { + //check for 'event' key + eventTypeArgs = metaItem.getArgsByKey('event'); + } + if (eventTypeArgs.length) { + eventListObj[MetaDataArgDefinition(eventTypeArgs[0]).value] = true; + } + } else { + if (meta == BINDABLE) { + eventListObj[ValueChangeEvent.VALUE_CHANGE] = true; + } + else { + trace("warning: unconverted change events metadata in class '" + + typeDefinition.name + "'", metaItem); + } + + } + } + } } } } diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/binding/utils/ChangeWatcher.as b/frameworks/projects/MXRoyale/src/main/royale/mx/binding/utils/ChangeWatcher.as index addd3aa..713af62 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/mx/binding/utils/ChangeWatcher.as +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/binding/utils/ChangeWatcher.as @@ -26,10 +26,10 @@ package mx.binding.utils import org.apache.royale.events.IEventDispatcher; import org.apache.royale.events.Event; -import mx.core.EventPriority; +//import mx.core.EventPriority; import mx.binding.BindabilityInfo; import mx.events.PropertyChangeEvent; -// import mx.utils.DescribeTypeCache; +import org.apache.royale.events.ValueChangeEvent; /** * The ChangeWatcher class defines utility methods @@ -140,9 +140,7 @@ public class ChangeWatcher * @productversion Flex 3 */ public static function watch(host:Object, chain:Object, - handler:Function, - commitOnly:Boolean = false, - useWeakReference:Boolean = false):ChangeWatcher + handler:Function):ChangeWatcher { if (!(chain is Array)) chain = [ chain ]; @@ -150,9 +148,8 @@ public class ChangeWatcher if (chain.length > 0) { var w:ChangeWatcher = - new ChangeWatcher(chain[0], handler, commitOnly, - watch(null, chain.slice(1), handler, commitOnly)); - w.useWeakReference = useWeakReference; + new ChangeWatcher(chain[0], handler, + watch(null, chain.slice(1), handler)); w.reset(host); return w; } @@ -187,10 +184,9 @@ public class ChangeWatcher * @playerversion AIR 1.1 * @productversion Flex 3 */ - public static function canWatch(host:Object, name:String, - commitOnly:Boolean = false):Boolean + public static function canWatch(host:Object, name:String):Boolean { - return !isEmpty(getEvents(host, name, commitOnly)); + return !isEmpty(getEvents(host, name)); } /** @@ -213,16 +209,14 @@ public class ChangeWatcher * @playerversion AIR 1.1 * @productversion Flex 3 */ - public static function getEvents(host:Object, name:String, - commitOnly:Boolean = false):Object + public static function getEvents(host:Object, name:String):Object { if (host is IEventDispatcher) { // Get { eventName: isCommitting, ... } for all change events // defined by host's class on prop <name> - /*var allEvents:Object = DescribeTypeCache.describeType(host). - bindabilityInfo.getChangeEvents(name); - if (commitOnly) + var allEvents:Object = BindabilityInfo.getCachedInfo(host).getChangeEvents(name); + /*if (commitOnly) { // Filter out non-committing events. var commitOnlyEvents:Object = {}; @@ -234,7 +228,9 @@ public class ChangeWatcher else { return allEvents; - }*/return {}; + }return {};*/ + + return allEvents; } else { @@ -285,7 +281,6 @@ public class ChangeWatcher * @productversion Flex 3 */ public function ChangeWatcher(access:Object, handler:Function, - commitOnly:Boolean = false, next:ChangeWatcher = null) { super(); @@ -294,10 +289,10 @@ public class ChangeWatcher name = access is String ? access as String : access.name; getter = access is String ? null : access.getter; this.handler = handler; - this.commitOnly = commitOnly; + // this.commitOnly = commitOnly; this.next = next; events = {}; - useWeakReference = false; + // useWeakReference = false; isExecuting = false; } @@ -361,7 +356,7 @@ public class ChangeWatcher * @playerversion AIR 1.1 * @productversion Flex 3 */ - private var commitOnly:Boolean; + // private var commitOnly:Boolean; /** * If watching a chain, this is a watcher on the next property @@ -418,7 +413,7 @@ public class ChangeWatcher * * @royalesuppresspublicvarwarning */ - public var useWeakReference:Boolean; + // public var useWeakReference:Boolean; //-------------------------------------------------------------------------- // @@ -527,18 +522,18 @@ public class ChangeWatcher { host.removeEventListener(p, wrapHandler); } - events = {}; + if (newHost == null) events = {}; } host = newHost; if (host != null) { - events = getEvents(host, name, commitOnly); + events = getEvents(host, name); for (p in events) { - host.addEventListener(p, wrapHandler, false, - EventPriority.BINDING, useWeakReference); + host.addEventListener(p, wrapHandler, false/*, + EventPriority.BINDING, useWeakReference*/); } } @@ -561,6 +556,7 @@ public class ChangeWatcher * @private * Listener for change events. * Resets chained watchers and calls user-supplied handler. + * */ private function wrapHandler(event:Event):void { @@ -573,10 +569,14 @@ public class ChangeWatcher if (next) next.reset(getHostPropertyValue()); - if (event is PropertyChangeEvent) + if (event is ValueChangeEvent){ + if ((event as ValueChangeEvent).propertyName == name) + handler(event); + } + else if (event is PropertyChangeEvent) { if ((event as PropertyChangeEvent).property == name) - handler(event as PropertyChangeEvent); + handler(event); } else {
