You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/04/24 06:55:51 UTC

[royale-asjs] 01/06: Ported support for ChangeWatcher.watch (without weakReference)

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 <gr...@gmail.com>
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
                 {