Skip to content

Commit

Permalink
Binding upgrades :
Browse files Browse the repository at this point in the history
-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.
  • Loading branch information
greg-dove committed May 22, 2020
1 parent 6557ac8 commit 96b42e5
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 26 deletions.
Expand Up @@ -45,6 +45,7 @@ public static class PropertyNodes
public ITypeDefinition type;
public boolean resolvedExport;
public String name;
public String originalName;
public String uri;
public boolean suppressExport;
}
Expand Down
Expand Up @@ -277,7 +277,7 @@ public void emit(IClassDefinition definition)
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);
Expand Down Expand Up @@ -719,6 +719,7 @@ public void emitGet(IGetterNode node)
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();
Expand Down Expand Up @@ -769,6 +770,7 @@ public void emitSet(ISetterNode node)
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();
Expand Down
Expand Up @@ -52,6 +52,7 @@
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;

/**
Expand Down Expand Up @@ -940,4 +941,8 @@ public static boolean isCustomNamespace(String ns) {
return false;
}

public static final String getClassDepthNameBase(String base, IClassDefinition definition, ICompilerProject project) {
return base + "_" + DefinitionUtils.deltaFromObject(definition, project) +"_";
}

}
Expand Up @@ -38,6 +38,7 @@
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;
Expand Down Expand Up @@ -355,16 +356,22 @@ public void emitEventSpecifier(IMXMLEventSpecifierNode node)
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();
Expand Down Expand Up @@ -406,8 +413,14 @@ public void emitInstance(IMXMLInstanceNode node)
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;
Expand Down
Expand Up @@ -77,6 +77,7 @@
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;
Expand All @@ -101,6 +102,7 @@
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;
Expand Down Expand Up @@ -1469,7 +1471,9 @@ protected void emitPropertyDecls()
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);
}
}
Expand Down Expand Up @@ -1501,6 +1505,12 @@ private void outputBindingInfoAsData(String cname, BindingDatabase bindingDataBa
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;
Expand Down Expand Up @@ -2252,8 +2262,16 @@ public void emitEventSpecifier(IMXMLEventSpecifierNode node)
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();
Expand Down
Expand Up @@ -39,6 +39,7 @@
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;
Expand All @@ -48,6 +49,7 @@
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;
Expand All @@ -68,6 +70,7 @@
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;
Expand Down Expand Up @@ -522,9 +525,10 @@ public void setTargetSettings(ITargetSettings value)
}

@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()
Expand Down
Expand Up @@ -22,6 +22,7 @@
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
Expand All @@ -34,4 +35,15 @@ public static final boolean isMemberDefinition(IDefinition definition)
&& (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;
}


}
Expand Up @@ -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
Expand Down
Expand Up @@ -27,9 +27,7 @@
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;
Expand Down Expand Up @@ -65,6 +63,20 @@ public 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 ****************/

Expand Down Expand Up @@ -337,6 +349,10 @@ private boolean objIsType(WatcherInfoBase obj, WatcherType type)
public String toString()
{
StringBuilder sb = new StringBuilder();

if (nearestAncestorBindings != null) {
sb.append("<ancestor bindings also exist at "+ nearestAncestorBindings+ " >");
}

if (bindingInfoSet.isEmpty())
{
Expand Down
Expand Up @@ -33,6 +33,8 @@
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;
Expand Down Expand Up @@ -63,9 +65,10 @@
* 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
Expand Down Expand Up @@ -145,6 +148,15 @@ public InstructionList getConstructorCode()
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
Expand All @@ -159,8 +171,15 @@ public InstructionList getConstructorCode()
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
{
Expand All @@ -169,8 +188,14 @@ public InstructionList getConstructorCode()
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())
Expand All @@ -191,11 +216,20 @@ public InstructionList getConstructorCode()

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++;
Expand Down
Expand Up @@ -1383,6 +1383,18 @@ public void setExcludedClass()
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>.
Expand Down

0 comments on commit 96b42e5

Please sign in to comment.