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/05/22 10:30:54 UTC

[royale-asjs] 02/03: Binding overhaul. -Support for inherited bindings (ancestor bindings get processed first) -slightly reduced release build size for most users. -fix for #456

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 c3ed62dd1f6945aca48d2b52174f73111b1f3e23
Author: greg-dove <gr...@gmail.com>
AuthorDate: Fri May 22 21:44:07 2020 +1200

    Binding overhaul.
    -Support for inherited bindings (ancestor bindings get processed first)
    -slightly reduced release build size for most users.
    -fix for #456
---
 .../royale/binding/ApplicationDataBinding.as       | 39 ++-------
 .../apache/royale/binding/ContainerDataBinding.as  | 70 +++++++---------
 .../org/apache/royale/binding/DataBindingBase.as   | 92 +++++++++++++++++++++-
 .../org/apache/royale/binding/GenericBinding.as    |  2 +
 .../royale/binding/ItemRendererDataBinding.as      | 34 +++-----
 .../royale/binding/MXMLBeadViewDataBinding.as      | 34 +++-----
 .../org/apache/royale/binding/ViewDataBinding.as   | 55 ++++++-------
 .../org/apache/royale/crux/binding/CruxBinding.as  |  2 +
 8 files changed, 172 insertions(+), 156 deletions(-)

diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ApplicationDataBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ApplicationDataBinding.as
index 9e0ef8f..1e3e55d 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ApplicationDataBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ApplicationDataBinding.as
@@ -59,39 +59,23 @@ package org.apache.royale.binding
 		public function ApplicationDataBinding()
 		{
 			super();
+            initEventType = 'viewChanged';
 		}
 
-        /**
-         *  @copy org.apache.royale.core.IBead#strand
-         *
-         *  @langversion 3.0
-         *  @playerversion Flash 10.2
-         *  @playerversion AIR 2.6
-         *  @productversion Royale 0.0
-         *  @royaleignorecoercion org.apache.royale.events.IEventDispatcher
-         */
-        override public function set strand(value:IStrand):void
-        {
-            _strand = value;
-            IEventDispatcher(_strand).addEventListener("viewChanged", viewChangedHandler);
-        }
+
         /**
          * @royaleignorecoercion org.apache.royale.core.IBinding
          * @royaleignorecoercion String
+         * @private
          */
-        private function viewChangedHandler(event:Event):void
-        {
-            if (!("_bindings" in _strand))
-                return;
-
+        override protected function processBindingData(bindingData:Array, first:int):void{
             var fieldWatcher:Object;
             var sb:SimpleBinding;
-            var bindingData:Array = _strand["_bindings"];
-            var n:int = bindingData[0];
-            var bindings:Array = [];
             var binding:Object = null;
+            var n:int = bindingData[first];
+            var bindings:Array = [];
             var i:int;
-            var index:int = 1;
+            var index:int = first + 1;
             for (i = 0; i < n; i++)
             {
                 binding = {};
@@ -159,14 +143,5 @@ package org.apache.royale.binding
             }
         }
 
-        private function makeGenericBinding(binding:Object, index:int, watchers:Object):void
-        {
-            var gb:GenericBinding = new GenericBinding();
-            gb.setDocument(_strand);
-            gb.destinationData = binding.destination;
-			gb.destinationFunction = binding.destFunc;
-            gb.source = binding.source;
-            setupWatchers(gb, index, watchers.watchers, null);
-        }
     }
 }
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ContainerDataBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ContainerDataBinding.as
index e2c4ffe..4ad00cb 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ContainerDataBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ContainerDataBinding.as
@@ -61,29 +61,25 @@ package org.apache.royale.binding
 		}
 
         /**
-         * @royaleignorecoercion String
          * @royaleignorecoercion org.apache.royale.core.IBinding
+         * @royaleignorecoercion String
+         * @private
          */
-        override protected function initBindingsHandler(event:Event):void
-        {
-            super.initBindingsHandler(event);
-
-            if (!("_bindings" in _strand))
-                return;
+        override protected function processBindingData(bindingData:Array, first:int):void{
             var fieldWatcher:Object;
             var sb:SimpleBinding;
             var cb:ConstantBinding;
-            var bindingData:Array = _strand["_bindings"];
+            var destinationObject:Object;
             var binding:Object = null;
-            var n:int = bindingData[0];
+            var n:int = bindingData[first];
             var bindings:Array = [];
             var i:int;
-            var index:int = 1;
+            var index:int = first + 1;
             for (i = 0; i < n; i++)
             {
                 binding = {};
                 binding.source = bindingData[index++];
-				binding.destFunc = bindingData[index++];
+                binding.destFunc = bindingData[index++];
                 binding.destination = bindingData[index++];
                 bindings.push(binding);
             }
@@ -96,7 +92,8 @@ package org.apache.royale.binding
                     if (binding.source[0] in _strand)
                     {
                         var compWatcher:Object;
-                        if (binding.source.length == 2 && binding.destination.length == 2)
+                        var simpleDest:Boolean = typeof binding.destination == 'string';
+                        if (binding.source.length == 2 && (simpleDest || binding.destination.length == 2 ))
                         {
                             // simple component.property binding
                             // can be simplebinding or constantbinding
@@ -109,13 +106,20 @@ package org.apache.royale.binding
                             if (fieldWatcher && fieldWatcher.eventNames is String)
                             {
                                 sb = new SimpleBinding();
-                                sb.destinationPropertyName = binding.destination[1];
+
+                                sb.destinationPropertyName = simpleDest ? binding.destination : binding.destination[1];
                                 sb.eventName = fieldWatcher.eventNames as String;
+                                if (simpleDest || binding.destination[0] == 'this') {
+                                    sb.destination = _strand;
+                                } else {
+                                    //how do we detect if destination root changes in a simplebinding?
+                                    sb.destination = _strand[binding.destination[0]]
+                                }
                                 sb.sourceID = binding.source[0];
                                 sb.sourcePropertyName = binding.source[1];
                                 sb.setDocument(_strand);
 
-                                prepareCreatedBinding(sb as IBinding, binding);
+                                prepareCreatedBinding(sb as IBinding, binding, destinationObject);
                             }
                             else if (fieldWatcher && fieldWatcher.eventNames == null)
                             {
@@ -140,14 +144,14 @@ package org.apache.royale.binding
                             chb.setDocument(_strand);
                             _strand.addBead(chb);
                         }
-                     }
-                     else if (binding.destination is Array)
-                     {
-                         makeConstantBinding(binding);
-                     }
-                     else  {
-                         makeGenericBinding(binding, i, watchers);
-                     }
+                    }
+                    else if (binding.destination is Array)
+                    {
+                        makeConstantBinding(binding);
+                    }
+                    else  {
+                        makeGenericBinding(binding, i, watchers);
+                    }
                 }
                 else if (binding.source is String && binding.destination is Array)
                 {
@@ -158,7 +162,7 @@ package org.apache.royale.binding
                         cb.destinationPropertyName = binding.destination[1];
                         cb.sourcePropertyName = binding.source;
                         cb.setDocument(_strand);
-                        var destinationObject:Object = null;
+                        destinationObject = null;
                         if (binding.destination[0] == "this")
                         {
                             destinationObject = _strand;
@@ -181,6 +185,7 @@ package org.apache.royale.binding
 
                         prepareCreatedBinding(sb as IBinding, binding);
                     }
+                    //else? is there anything missing here? tbc
                 }
                 else  {
                     makeGenericBinding(binding, i, watchers);
@@ -190,24 +195,5 @@ package org.apache.royale.binding
             }
         }
 
-        private function makeGenericBinding(binding:Object, index:int, watchers:Object):void
-        {
-            var gb:GenericBinding = new GenericBinding();
-            gb.setDocument(_strand);
-            gb.destinationData = binding.destination;
-			gb.destinationFunction = binding.destFunc;
-            gb.source = binding.source;
-            if (watchers.watchers.length)
-            {
-                setupWatchers(gb, index, watchers.watchers, null);
-            }
-            else
-            {
-                // should be a constant expression.
-                // the value doesn't matter as GenericBinding
-                // should get the value from the source
-                gb.valueChanged(null, true);
-            }
-        }
     }
 }
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/DataBindingBase.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/DataBindingBase.as
index e7c3f5b..dd45b24 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/DataBindingBase.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/DataBindingBase.as
@@ -51,6 +51,28 @@ package org.apache.royale.binding
 
         protected var deferredBindings:Object;
 
+        protected var initEventType:String = "initBindings";
+
+        private var _initialized:Boolean;
+
+        /**
+         * This method is a way to manually initialize the binding support at an earlier time than would
+         * happen by default ( this is usually the timing of 'initBindings' but could vary according to the
+         * timing of whatever initTypeEvent is for a particular sub-class)
+         * This can be useful in some cases when porting legacy code that expects bindings to be active
+         * at a certain alternate time, e.g. before mxml content is created and assigned, for example.
+         *
+         * This method will be dead-code-eliminated in js-release builds if not used in an application's code
+         *
+         * @royalesuppressexport
+         */
+        public function initializeNow():void{
+            if (!_initialized) {
+                IEventDispatcher(_strand).removeEventListener(initEventType, processBindings);
+                processBindings(null);
+            }
+        }
+
         /**
          *  @copy org.apache.royale.core.IBead#strand
          *
@@ -63,11 +85,54 @@ package org.apache.royale.binding
         public function set strand(value:IStrand):void
         {
             _strand = value;
-            IEventDispatcher(_strand).addEventListener("initBindings", initBindingsHandler);
+            if (!_initialized)
+                IEventDispatcher(_strand).addEventListener(initEventType, processBindings);
         }
 
-        protected function initBindingsHandler(event:Event):void
-        {
+        private var _ancestry:Array;
+        protected function processBindings(event:Event):void{
+            if (!("_bindings" in _strand) ||  _initialized)
+                return;
+            _initialized = true;
+            var bindingData:Array = _strand["_bindings"];
+            var first:int = 0;
+            if (bindingData[0] is Array) {
+                _ancestry = [];
+                //process ancestor bindings
+                processAncestors(bindingData[0] as Array, _ancestry);
+                first = 1;
+            }
+            processBindingData(bindingData, first);
+        }
+
+        /**
+         *
+         * @param array the binding data to process
+         * @param strongRefs, an array to push the ancestry items into, stored in the 'parent' DataBindingBase as a private var
+         *
+         * @royaleignorecoercion org.apache.royale.binding.DataBindingBase
+         * @royaleignorecoercion Class
+         */
+        private function processAncestors(array:Array, strongRefs:Array):void{
+            var first:int = 0;
+            var inst:DataBindingBase;
+            var bindingClass:Class = Object(this).constructor as Class;
+            if (array[0] is Array) {
+                //recurse into any more distant ancestors
+                inst = new bindingClass() as DataBindingBase;
+                inst._strand = _strand;
+                strongRefs.push(inst);
+                inst.processAncestors(array[0] as Array, strongRefs);
+                first = 1;
+            }
+            inst = new bindingClass() as DataBindingBase;
+            inst._strand = _strand;
+            strongRefs.push(inst);
+            inst.processBindingData(array, first)
+        }
+
+        protected function processBindingData(array:Array, first:int):void{
+
         }
 
         /**
@@ -324,6 +389,27 @@ package org.apache.royale.binding
             prepareCreatedBinding(cb as IBinding, binding);
         }
 
+        protected function makeGenericBinding(binding:Object, index:int, watchers:Object):void
+        {
+            var gb:GenericBinding = new GenericBinding();
+            gb.setDocument(_strand);
+            gb.destinationData = binding.destination;
+            gb.destinationFunction = binding.destFunc;
+            gb.source = binding.source;
+            if (watchers.watchers.length)
+            {
+                setupWatchers(gb, index, watchers.watchers, null);
+            }
+            else
+            {
+                // should be a constant expression.
+                // the value doesn't matter as GenericBinding
+                // should get the value from the source
+                gb.valueChanged(null, true);
+            }
+        }
+
+
         /**
          */
         private function deferredBindingsHandler(event:Event):void
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/GenericBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/GenericBinding.as
index e75d7ed..8217f15 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/GenericBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/GenericBinding.as
@@ -220,6 +220,8 @@ package org.apache.royale.binding
                         return;
                 }
                 obj[arr[n-1]] = value;                
+            } else if (destinationData is String) {
+                document[destinationData] = value;
             }
         }
 		
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ItemRendererDataBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ItemRendererDataBinding.as
index cac8186..19ad524 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ItemRendererDataBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ItemRendererDataBinding.as
@@ -57,21 +57,20 @@ package org.apache.royale.binding
 			super();
 		}
 
-        override protected function initBindingsHandler(event:Event):void
-        {
-            super.initBindingsHandler(event);
-
-            if (!("_bindings" in _strand))
-                return;
-
+        /**
+         * @royaleignorecoercion org.apache.royale.core.IBinding
+         * @royaleignorecoercion String
+         * @private
+         */
+        override protected function processBindingData(bindingData:Array, first:int):void{
             var fieldWatcher:Object;
             var sb:SimpleBinding;
-            var bindingData:Array = _strand["_bindings"];
-            var n:int = bindingData[0];
-            var bindings:Array = [];
+            var cb:ConstantBinding;
             var binding:Object = null;
+            var n:int = bindingData[first];
+            var bindings:Array = [];
             var i:int;
-            var index:int = 1;
+            var index:int = first + 1;
             for (i = 0; i < n; i++)
             {
                 binding = {};
@@ -122,8 +121,8 @@ package org.apache.royale.binding
 
                     if (compWatcher && fieldWatcher &&
                             (binding.source[0] == "data" ||
-                            (compWatcher.eventNames is String &&
-                            compWatcher.eventNames == "dataChange")))
+                                    (compWatcher.eventNames is String &&
+                                            compWatcher.eventNames == "dataChange")))
                     {
                         var irsb:ItemRendererSimpleBinding = new ItemRendererSimpleBinding();
                         irsb.destinationID = binding.destination[0];
@@ -157,14 +156,5 @@ package org.apache.royale.binding
             }
         }
 
-        private function makeGenericBinding(binding:Object, index:int, watchers:Object):void
-        {
-            var gb:GenericBinding = new GenericBinding();
-            gb.setDocument(_strand);
-            gb.destinationData = binding.destination;
-			gb.destinationFunction = binding.destFunc;
-            gb.source = binding.source;
-            setupWatchers(gb, index, watchers.watchers, null);
-        }
     }
 }
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/MXMLBeadViewDataBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/MXMLBeadViewDataBinding.as
index 2cd58f9..9cb7be3 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/MXMLBeadViewDataBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/MXMLBeadViewDataBinding.as
@@ -57,30 +57,24 @@ package org.apache.royale.binding
 			super();
 		}
 
+
         /**
-         * @royaleignorecoercion String
          * @royaleignorecoercion org.apache.royale.core.IBinding
+         * @royaleignorecoercion String
+         * @private
          */
-        override protected function initBindingsHandler(event:Event):void
-        {
-            super.initBindingsHandler(event);
-
-            if (!("_bindings" in _strand))
-                return;
-
+        override protected function processBindingData(bindingData:Array, first:int):void {
             var fieldWatcher:Object;
             var sb:SimpleBinding;
-            var bindingData:Array = _strand["_bindings"];
-            var n:int = bindingData[0];
-            var bindings:Array = [];
             var binding:Object = null;
+            var n:int = bindingData[first];
+            var bindings:Array = [];
             var i:int;
-            var index:int = 1;
-            for (i = 0; i < n; i++)
-            {
+            var index:int = first + 1;
+            for (i = 0; i < n; i++) {
                 binding = {};
                 binding.source = bindingData[index++];
-				binding.destFunc = bindingData[index++];
+                binding.destFunc = bindingData[index++];
                 binding.destination = bindingData[index++];
                 bindings.push(binding);
             }
@@ -147,16 +141,8 @@ package org.apache.royale.binding
 
                 fieldWatcher = null;
             }
-        }
 
-        private function makeGenericBinding(binding:Object, index:int, watchers:Object):void
-        {
-            var gb:GenericBinding = new GenericBinding();
-            gb.setDocument(_strand);
-            gb.destinationData = binding.destination;
-			gb.destinationFunction = binding.destFunc;
-            gb.source = binding.source;
-            setupWatchers(gb, index, watchers.watchers, null);
         }
+
     }
 }
diff --git a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ViewDataBinding.as b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ViewDataBinding.as
index ded61fe..aedcad0 100644
--- a/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ViewDataBinding.as
+++ b/frameworks/projects/Binding/src/main/royale/org/apache/royale/binding/ViewDataBinding.as
@@ -58,26 +58,24 @@ package org.apache.royale.binding
 			super();
 		}
 
-        override protected function initBindingsHandler(event:Event):void
-        {
-            super.initBindingsHandler(event);
-
-            if (!("_bindings" in _strand))
-                return;
 
+        /**
+         * @royaleignorecoercion org.apache.royale.core.IBinding
+         * @royaleignorecoercion String
+         * @private
+         */
+        override protected function processBindingData(bindingData:Array, first:int):void {
             var fieldWatcher:Object;
             var sb:SimpleBinding;
-            var bindingData:Array = _strand["_bindings"];
-            var n:int = bindingData[0];
-            var bindings:Array = [];
             var binding:Object = null;
+            var n:int = bindingData[first];
+            var bindings:Array = [];
             var i:int;
-            var index:int = 1;
-            for (i = 0; i < n; i++)
-            {
+            var index:int = first + 1;
+            for (i = 0; i < n; i++) {
                 binding = {};
                 binding.source = bindingData[index++];
-				binding.destFunc = bindingData[index++];
+                binding.destFunc = bindingData[index++];
                 binding.destination = bindingData[index++];
                 bindings.push(binding);
             }
@@ -114,7 +112,7 @@ package org.apache.royale.binding
                     }
                 }
                 else if (binding.source is Array
-                    && binding.source.length == 2 && binding.destination.length == 2)
+                        && binding.source.length == 2 && binding.destination.length == 2)
                 {
                     // can be simplebinding or constantbinding
                     compWatcher = watchers.watcherMap[binding.source[0]];
@@ -145,16 +143,16 @@ package org.apache.royale.binding
                         prepareCreatedBinding(cb as IBinding, binding);
                     }
                 }
-             /*   else if (binding.source is Array && binding.source[0] in _strand)
-                {
-                    compWatcher = watchers.watcherMap[binding.source[0]];
-                    var chb:ChainBinding = new ChainBinding();
-                    chb.destination = binding.destination;
-                    chb.source = binding.source;
-                    chb.watcherChain = compWatcher;
-                    chb.setDocument(_strand);
-                    _strand.addBead(chb);
-                } */
+                /*   else if (binding.source is Array && binding.source[0] in _strand)
+                   {
+                       compWatcher = watchers.watcherMap[binding.source[0]];
+                       var chb:ChainBinding = new ChainBinding();
+                       chb.destination = binding.destination;
+                       chb.source = binding.source;
+                       chb.watcherChain = compWatcher;
+                       chb.setDocument(_strand);
+                       _strand.addBead(chb);
+                   } */
                 else
                 {
                     makeGenericBinding(binding, i, watchers);
@@ -164,14 +162,5 @@ package org.apache.royale.binding
             }
         }
 
-        private function makeGenericBinding(binding:Object, index:int, watchers:Object):void
-        {
-            var gb:GenericBinding = new GenericBinding();
-            gb.setDocument(_strand);
-            gb.destinationData = binding.destination;
-			gb.destinationFunction = binding.destFunc;
-            gb.source = binding.source;
-            setupWatchers(gb, index, watchers.watchers, null);
-        }
     }
 }
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/binding/CruxBinding.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/binding/CruxBinding.as
index 09d8e08..5972f66 100644
--- a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/binding/CruxBinding.as
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/binding/CruxBinding.as
@@ -133,6 +133,8 @@ package org.apache.royale.crux.binding
                         return;
                 }
                 obj[arr[n-1]] = value;                
+            } else if (destinationData is String) {
+                document[destinationData] = value;
             }
         }