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:31:26 UTC

[royale-compiler] 01/02: Binding upgrades : -support for binding inheritance, similar to how Flex worked. -fix for conflicting generated ids in swf and js with mxml inheritance -fix for conflicing generated event handlers in js with mxml inheritance -fix for [Bindable]private getter/setter code gen in js.

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-compiler.git

commit 96b42e5a980c1d919d0c3a620c500f7a0aff2e9d
Author: greg-dove <gr...@gmail.com>
AuthorDate: Fri May 22 21:56:43 2020 +1200

    Binding upgrades :
    -support for binding inheritance, similar to how Flex worked.
    -fix for conflicting generated ids in swf and js with mxml inheritance
    -fix for conflicing generated event handlers in js with mxml inheritance
    -fix for [Bindable]private getter/setter code gen in js.
---
 .../internal/codegen/js/JSSessionModel.java        |  1 +
 .../internal/codegen/js/jx/AccessorEmitter.java    |  4 +-
 .../internal/codegen/js/utils/EmitterUtils.java    |  5 +++
 .../mxml/royale/MXMLRoyaleASDocEmitter.java        | 27 +++++++++---
 .../codegen/mxml/royale/MXMLRoyaleEmitter.java     | 24 +++++++++--
 .../internal/projects/RoyaleJSProject.java         |  8 +++-
 .../royale/compiler/utils/DefinitionUtils.java     | 12 ++++++
 .../constants/IMetaAttributeConstants.java         |  3 ++
 .../codegen/databinding/BindingDatabase.java       | 20 ++++++++-
 .../databinding/MXMLBindingDirectiveHelper.java    | 50 ++++++++++++++++++----
 .../internal/definitions/ClassDefinition.java      | 12 ++++++
 .../compiler/internal/projects/RoyaleProject.java  |  6 ++-
 .../tree/mxml/MXMLClassDefinitionNode.java         |  2 +-
 .../internal/units/MXMLCompilationUnit.java        |  3 ++
 14 files changed, 151 insertions(+), 26 deletions(-)

diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSSessionModel.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSSessionModel.java
index 6b6ca6d..86989f2 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSSessionModel.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSSessionModel.java
@@ -45,6 +45,7 @@ public class JSSessionModel
         public ITypeDefinition type;
         public boolean resolvedExport;
         public String name;
+        public String originalName;
         public String uri;
         public boolean suppressExport;
     }
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index e5a5998..f67b012 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -277,7 +277,7 @@ public class AccessorEmitter extends JSSubEmitter implements
 	                        write(ASEmitterTokens.PAREN_CLOSE);
 	                        writeNewline(ASEmitterTokens.SEMICOLON);
 	                        writeNewline("    this.dispatchEvent("+fjs.formatQualifiedName(BindableEmitter.VALUECHANGE_EVENT_QNAME)+".createUpdateEvent(");
-	                        writeNewline("         this, \"" + baseName + "\", oldValue, value));");
+	                        writeNewline("         this, \"" + p.originalName + "\", oldValue, value));");
 	                        writeNewline(ASEmitterTokens.BLOCK_CLOSE);
 	                        write(ASEmitterTokens.BLOCK_CLOSE);
 	                        write(ASEmitterTokens.SEMICOLON);                        
@@ -719,6 +719,7 @@ public class AccessorEmitter extends JSSubEmitter implements
             p = new PropertyNodes();
 			//track name and uri separately:
 			p.name = name;
+			p.originalName = node.getName();
 			p.uri = uri;
 			//resolvedExport is true if it is a custom namespace or one of a paired of accessor definitions is public
 			p.resolvedExport = uri != null || def.isPublic();
@@ -769,6 +770,7 @@ public class AccessorEmitter extends JSSubEmitter implements
             p = new PropertyNodes();
             //track name and uri separately:
             p.name = name;
+            p.originalName = node.getName();
             p.uri = uri;
  			//resolvedExport is true if it is a custom namespace or one of a paired of accessor definitions is public
             p.resolvedExport = uri != null || def.isPublic();
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
index 0be6c74..c260963 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
@@ -52,6 +52,7 @@ import org.apache.royale.compiler.internal.tree.as.ParameterNode;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.tree.ASTNodeID;
 import org.apache.royale.compiler.tree.as.*;
+import org.apache.royale.compiler.utils.DefinitionUtils;
 import org.apache.royale.compiler.utils.NativeUtils;
 
 /**
@@ -940,4 +941,8 @@ public class EmitterUtils
         return false;
     }
 
+    public static final String getClassDepthNameBase(String base, IClassDefinition definition, ICompilerProject project) {
+        return base + "_" + DefinitionUtils.deltaFromObject(definition, project) +"_";
+    }
+
 }
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleASDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleASDocEmitter.java
index 3aae3b8..14d6008 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleASDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleASDocEmitter.java
@@ -38,6 +38,7 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.databinding.BindingDatabase;
 import org.apache.royale.compiler.internal.codegen.databinding.BindingInfo;
 import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleASDocEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
 import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
 import org.apache.royale.compiler.internal.codegen.mxml.MXMLEmitter;
@@ -355,16 +356,22 @@ public class MXMLRoyaleASDocEmitter extends MXMLEmitter implements
         MXMLDescriptorSpecifier currentDescriptor = getCurrentDescriptor("i");
 
         MXMLEventSpecifier eventSpecifier = new MXMLEventSpecifier();
-        eventSpecifier.eventHandler = MXMLRoyaleEmitterTokens.EVENT_PREFIX
-                .getToken() + eventCounter++;
+        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter)asEmitter;
+
+        IClassDefinition currentClass = fjs.getModel().getCurrentClass();
+        //naming needs to avoid conflicts with ancestors - using delta from object which is
+        //a) short and b)provides a 'unique' (not zero risk, but very low risk) option
+        String nameBase = EmitterUtils.getClassDepthNameBase(MXMLRoyaleEmitterTokens.EVENT_PREFIX
+                .getToken(), currentClass, getMXMLWalker().getProject());
+        eventSpecifier.eventHandler = nameBase + eventCounter++;
+
         eventSpecifier.name = cdef.getBaseName();
         eventSpecifier.type = node.getEventParameterDefinition()
                 .getTypeAsDisplayString();
 
         eventHandlerNameMap.put(node, eventSpecifier.eventHandler);
-        
-        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
-                .getASEmitter();
+
 
         StringBuilder sb = null;
         int len = node.getChildCount();
@@ -406,8 +413,14 @@ public class MXMLRoyaleASDocEmitter extends MXMLEmitter implements
         String id = node.getID();
         if (id == null)
             id = node.getEffectiveID();
-        if (id == null)
-            id = MXMLRoyaleEmitterTokens.ID_PREFIX.getToken() + idCounter++;
+        if (id == null) {
+            IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
+            JSRoyaleEmitter fjs = (JSRoyaleEmitter)asEmitter;
+            IClassDefinition currentClass = fjs.getModel().getCurrentClass();
+            //naming needs to avoid conflicts with ancestors - using delta from object which is
+            //a) short and b)provides a 'unique' (not zero risk, but very low risk) option
+            id = EmitterUtils.getClassDepthNameBase(MXMLRoyaleEmitterTokens.ID_PREFIX.getToken(), currentClass, getMXMLWalker().getProject()) + idCounter++;
+        }
 
         MXMLDescriptorSpecifier currentInstance = new MXMLDescriptorSpecifier();
         currentInstance.isProperty = false;
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
index e8c8e2a..859823a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
@@ -77,6 +77,7 @@ import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
 import org.apache.royale.compiler.internal.codegen.js.jx.PackageFooterEmitter;
 import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
 import org.apache.royale.compiler.internal.codegen.mxml.MXMLEmitter;
+import org.apache.royale.compiler.internal.codegen.mxml.MXMLEmitterTokens;
 import org.apache.royale.compiler.internal.driver.js.royale.JSCSSCompilationSession;
 import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
 import org.apache.royale.compiler.internal.projects.RoyaleProject;
@@ -101,6 +102,7 @@ import org.apache.royale.compiler.tree.metadata.IMetaTagNode;
 import org.apache.royale.compiler.tree.metadata.IMetaTagsNode;
 import org.apache.royale.compiler.tree.mxml.*;
 import org.apache.royale.compiler.units.ICompilationUnit;
+import org.apache.royale.compiler.utils.DefinitionUtils;
 import org.apache.royale.compiler.utils.NativeUtils;
 import org.apache.royale.compiler.visitor.mxml.IMXMLBlockWalker;
 import org.apache.royale.swc.ISWC;
@@ -1469,7 +1471,9 @@ public class MXMLRoyaleEmitter extends MXMLEmitter implements
             writeNewline(" */");
             write(ASEmitterTokens.THIS);
             write(ASEmitterTokens.MEMBER_ACCESS);
-            write((instance.id != null ? instance.id : instance.effectiveId) + "_");
+            String id = instance.id != null ? instance.id : instance.effectiveId;
+            if (!id.startsWith(MXMLRoyaleEmitterTokens.ID_PREFIX.getToken())) id += "_";
+			write(id);
             writeNewline(ASEmitterTokens.SEMICOLON);
         }
     }
@@ -1501,6 +1505,12 @@ public class MXMLRoyaleEmitter extends MXMLEmitter implements
         writeNewline(formatQualifiedName(cname)
                 + ".prototype._bindings = [");
 
+		if (bindingDataBase.getHasAncestorBindings()) {
+			//reference the ancestor binding data (which may in turn reference its owner's ancestor's bindings etc)
+			writeNewline(formatQualifiedName(bindingDataBase.getNearestAncestorWithBindings()) +
+					 ".prototype._bindings,");
+		}
+
         Set<BindingInfo> bindingInfo = bindingDataBase.getBindingInfo();
         writeNewline(bindingInfo.size() + ","); // number of bindings
         boolean hadOutput = false;
@@ -2252,8 +2262,16 @@ public class MXMLRoyaleEmitter extends MXMLEmitter implements
         MXMLDescriptorSpecifier currentDescriptor = getCurrentDescriptor("i");
 
         MXMLEventSpecifier eventSpecifier = new MXMLEventSpecifier();
-        eventSpecifier.eventHandler = MXMLRoyaleEmitterTokens.EVENT_PREFIX
-                .getToken() + eventCounter++;
+
+		IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
+		JSRoyaleEmitter fjs = (JSRoyaleEmitter)asEmitter;
+
+		IClassDefinition currentClass = fjs.getModel().getCurrentClass();
+		//naming needs to avoid conflicts with ancestors - using delta from object which is
+		//a) short and b)provides a 'unique' (not zero risk, but very low risk) option
+        String nameBase = EmitterUtils.getClassDepthNameBase(MXMLRoyaleEmitterTokens.EVENT_PREFIX
+				.getToken(), currentClass, getMXMLWalker().getProject());
+        eventSpecifier.eventHandler = nameBase + eventCounter++;
         eventSpecifier.name = cdef.getBaseName();
         eventSpecifier.type = node.getEventParameterDefinition()
                 .getTypeAsDisplayString();
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
index acb4a2e..beedbe9 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.config.Configuration;
 import org.apache.royale.compiler.config.Configurator;
 import org.apache.royale.compiler.css.ICSSMediaQueryCondition;
 import org.apache.royale.compiler.css.ICSSRule;
+import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.definitions.IDefinition;
 import org.apache.royale.compiler.definitions.IFunctionDefinition;
 import org.apache.royale.compiler.definitions.ITypeDefinition;
@@ -48,6 +49,7 @@ import org.apache.royale.compiler.definitions.references.IResolvedQualifiersRefe
 import org.apache.royale.compiler.definitions.references.ReferenceFactory;
 import org.apache.royale.compiler.driver.IBackend;
 import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
 import org.apache.royale.compiler.internal.codegen.mxml.royale.MXMLRoyaleEmitterTokens;
 import org.apache.royale.compiler.internal.common.JSModuleRequireDescription;
 import org.apache.royale.compiler.internal.css.codegen.CSSCompilationSession;
@@ -68,6 +70,7 @@ import org.apache.royale.compiler.tree.as.IClassNode;
 import org.apache.royale.compiler.tree.as.IDefinitionNode;
 import org.apache.royale.compiler.tree.as.IDocumentableDefinitionNode;
 import org.apache.royale.compiler.tree.as.IInterfaceNode;
+import org.apache.royale.compiler.tree.mxml.IMXMLClassDefinitionNode;
 import org.apache.royale.compiler.units.ICompilationUnit;
 import org.apache.royale.compiler.units.ICompilationUnit.UnitType;
 import org.apache.royale.swc.ISWC;
@@ -522,9 +525,10 @@ public class RoyaleJSProject extends RoyaleProject
     }
     
     @Override
-    public String getGeneratedIDBase()
+    public String getGeneratedIDBase(IMXMLClassDefinitionNode definitionNode)
     {
-        return MXMLRoyaleEmitterTokens.ID_PREFIX.getToken();
+        IClassDefinition classDefinition = definitionNode.getDefinition();
+        return EmitterUtils.getClassDepthNameBase(MXMLRoyaleEmitterTokens.ID_PREFIX.getToken(), classDefinition, this);
     }
 
     public ITargetAttributes computeTargetAttributes()
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/DefinitionUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/DefinitionUtils.java
index 80b0ae4..40ec8e5 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/DefinitionUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/DefinitionUtils.java
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.utils;
 import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.definitions.IDefinition;
 import org.apache.royale.compiler.definitions.IInterfaceDefinition;
+import org.apache.royale.compiler.projects.ICompilerProject;
 
 /**
  * @author Michael Schmalle
@@ -34,4 +35,15 @@ public class DefinitionUtils
                 && (definition.getParent() instanceof IClassDefinition || definition
                         .getParent() instanceof IInterfaceDefinition);
     }
+
+
+    public static final int deltaFromObject(IClassDefinition definition, ICompilerProject project) {
+        int ret = -1;
+        if (definition != null) {
+            return definition.resolveAncestry(project).length - 1;
+        }
+        return ret;
+    }
+
+
 }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java b/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
index ecf8158..9412bcb 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
@@ -219,6 +219,9 @@ public interface IMetaAttributeConstants
     
     // [RoyaleArrayLike(...args)]
     static final String ATTRIBUTE_ARRAYLIKE = "RoyaleArrayLike";
+
+    // [RoyaleBindings] (added by compiler)
+    static final String ATTRIBUTE_BINDINGS= "RoyaleBindings";
 	
 	/**
 	 * List of metadata tags that do not inherit
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/BindingDatabase.java b/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/BindingDatabase.java
index d1df60c..d7a087a 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/BindingDatabase.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/BindingDatabase.java
@@ -27,9 +27,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.WeakHashMap;
 
-import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.internal.as.codegen.MXMLClassDirectiveProcessor;
 import org.apache.royale.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
 import org.apache.royale.compiler.internal.scopes.ASScope;
@@ -65,6 +63,20 @@ public class BindingDatabase
             _diagnosticLogger.add(this);
         }
     }
+
+    private String nearestAncestorBindings = null;
+
+    public Boolean getHasAncestorBindings(){
+        return nearestAncestorBindings != null;
+    }
+
+    public void setNearestAncestorWithBindings(String value){
+        nearestAncestorBindings = value;
+    }
+
+    public String getNearestAncestorWithBindings(){
+        return nearestAncestorBindings;
+    }
     
     /************** private data ****************/
      
@@ -337,6 +349,10 @@ public class BindingDatabase
     public String toString()
     {
         StringBuilder sb = new StringBuilder();
+
+        if (nearestAncestorBindings != null) {
+            sb.append("<ancestor bindings also exist at "+ nearestAncestorBindings+ " >");
+        }
         
         if (bindingInfoSet.isEmpty())
         {
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java b/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
index a5a2fe6..ea82e09 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
@@ -33,6 +33,8 @@ import org.apache.royale.abc.semantics.Name;
 import org.apache.royale.abc.visitors.IABCVisitor;
 import org.apache.royale.compiler.common.DependencyType;
 import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.constants.IMetaAttributeConstants;
+import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.definitions.IDefinition;
 import org.apache.royale.compiler.definitions.references.IResolvedQualifiersReference;
 import org.apache.royale.compiler.definitions.references.ReferenceFactory;
@@ -63,9 +65,10 @@ import org.apache.royale.compiler.workspaces.IWorkspace;
  * TODO: 
  *      Document the runtime dependencies on SDK
  *      add problem reporting.
- *      
+ *
+ *      bind to function, This should be fixed now
  * Cases not yet working:
- *      bind to function, xml, xml list, array
+ *      xml, xml list, array
  *      
  * Improve code gen
  *      don't make getter functions when not needed
@@ -145,6 +148,15 @@ public class MXMLBindingDirectiveHelper
                 return null;
        
         bindingDataBase.finishAnalysis();
+
+        for (IClassDefinition ancestor: host.getClassDefinition().resolveAncestry(host.getProject())) {
+            if (ancestor.equals(host.getClassDefinition())) continue;
+            if (ancestor.getMetaTagByName(IMetaAttributeConstants.ATTRIBUTE_BINDINGS) != null) {
+                //System.out.println("Ancestor bindings for "+host.getClassDefinition().getQualifiedName()+" at "+ancestor.getQualifiedName());
+                bindingDataBase.setNearestAncestorWithBindings(ancestor.getQualifiedName());
+                break;
+            }
+        }
         
         // Please leave this in here - it is a very commonly used diagnostic
         // Just comment it out before checking
@@ -159,8 +171,15 @@ public class MXMLBindingDirectiveHelper
                 makeSpecialMemberVariablesForBinding();
                 isFlexSDK = true;
             }
-            else
-                host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE);
+            else {
+                //if the variable is already declared on an ancestor, we should not redeclare it (as it is currently public)
+                //redeclaring it will essentially prevent the inherited value from being accessed at the current level (in swf)
+                //accessing the super class value allows 'nesting' which permits inheritance
+                if (!bindingDataBase.getHasAncestorBindings())
+                    host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE);
+                //this should already be set, the following may be able to be removed (tbc):
+                host.getClassDefinition().setRoyaleBindings();
+            }
         }
         else
         {
@@ -169,8 +188,14 @@ public class MXMLBindingDirectiveHelper
                 makeSpecialMemberVariablesForBinding();
                 isFlexSDK = true;
             }
-            else
-                host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE);
+            else{
+                //redeclaring it will essentially prevent the inherited value from being accessed at the current level (in swf)
+                if (!bindingDataBase.getHasAncestorBindings())
+                    host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE);
+                //this should already be set, the following may be able to be removed (tbc):
+                host.getClassDefinition().setRoyaleBindings();
+
+            }
         }
         
         if (host.getProject().getTargetSettings().getMxmlChildrenAsData())
@@ -191,11 +216,20 @@ public class MXMLBindingDirectiveHelper
     
     private InstructionList outputBindingInfoAsData(boolean isFlexSDK)
     {
-        //System.out.println("outputBindingInfoAsData");
 
         InstructionList ret = new InstructionList();
         int propertyCount = 0;
-        
+        if (!isFlexSDK && bindingDataBase.getHasAncestorBindings()) {
+            //add the ancestor bindings reference as the first item in this current _bindings array
+            //this approach permits binding evaluation to work recursively by checking the first element only
+
+            ret.addInstruction(OP_getlocal0);
+            // stack: ..., this
+            ret.addInstruction(OP_getproperty, IMXMLTypeConstants.NAME_BINDINGS);
+            //propertyCount needs to be incremented for the current array:
+            propertyCount++;
+        }
+
         Set<BindingInfo> bindingInfo = bindingDataBase.getBindingInfo();
         ret.pushNumericConstant(bindingInfo.size()); // number of bindings
         propertyCount++;
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
index 85a6900..0454ef2 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
@@ -1383,6 +1383,18 @@ public class ClassDefinition extends ClassDefinitionBase implements IClassDefini
         addMetaTag(excludeClassMetaTag);
     }
 
+
+    /**
+     * Mark this class as being generated with mxml bindings [RoyaleBindings] meta data.
+     */
+    public void setRoyaleBindings()
+    {
+        if (!hasMetaTagByName(IMetaAttributeConstants.ATTRIBUTE_BINDINGS)) {
+            MetaTag bindingsMarker = new MetaTag(this, IMetaAttributeConstants.ATTRIBUTE_BINDINGS, new IMetaTagAttribute[0]);
+            addMetaTag(bindingsMarker);
+        }
+    }
+
     /**
      * For debugging only. Produces a string such as
      * <code>public class B extends A implements I1, I2</code>.
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
index b85c412..11f89b5 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
@@ -92,6 +92,7 @@ import org.apache.royale.compiler.targets.ITargetSettings;
 import org.apache.royale.compiler.tree.ASTNodeID;
 import org.apache.royale.compiler.tree.as.IASNode;
 import org.apache.royale.compiler.tree.as.IImportNode;
+import org.apache.royale.compiler.tree.mxml.IMXMLClassDefinitionNode;
 import org.apache.royale.compiler.units.ICompilationUnit;
 import org.apache.royale.compiler.units.requests.IOutgoingDependenciesRequestResult;
 import org.apache.royale.compiler.units.requests.IRequest;
@@ -2249,9 +2250,10 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile
      * it isn't allowed in an ActionScript identifier or MXML id. It also can't
      * conflict with any dynamic properties, because MXML classes are sealed.
      */
-    public String getGeneratedIDBase()
+    public String getGeneratedIDBase(IMXMLClassDefinitionNode definitionNode)
     {
-        return "#";
+        IClassDefinition classDefinition = definitionNode.getDefinition();
+        return "#_"+classDefinition.resolveAncestry(this).length+"_";
     }
     
     @Override
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
index 5cfd2d2..e4d16f9 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
@@ -754,7 +754,7 @@ public class MXMLClassDefinitionNode extends MXMLClassReferenceNodeBase
         {
             if (generatedIDMap.containsKey(instanceNode))
                 return;
-            String id = project.getGeneratedIDBase() + generatedIDCounter++;
+            String id = project.getGeneratedIDBase(this) + generatedIDCounter++;
             generatedIDMap.put(instanceNode, id);
         }
     }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/units/MXMLCompilationUnit.java b/compiler/src/main/java/org/apache/royale/compiler/internal/units/MXMLCompilationUnit.java
index 13c587b..e8f000d 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/units/MXMLCompilationUnit.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/units/MXMLCompilationUnit.java
@@ -114,6 +114,9 @@ public class MXMLCompilationUnit extends CompilationUnitBase
                 {
                     TypeScope mainClassScope = (TypeScope)mainClassDefinition.getContainedScope();
                     documentNode.setScope(mainClassScope);
+                    if (documentNode.getHasDataBindings()) {
+                        mainClassDefinition.setRoyaleBindings();
+                    }
                 }
             }