You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2019/11/07 21:56:49 UTC

[royale-compiler] 01/02: fix binding in fx:XMLList. Fixes apache/royale-asjs#545

This is an automated email from the ASF dual-hosted git repository.

aharui pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 2b518588cd79db84a5c96e2bbd177227e52cec4e
Author: Alex Harui <ah...@apache.org>
AuthorDate: Wed Nov 6 17:11:56 2019 -0800

    fix binding in fx:XMLList.  Fixes apache/royale-asjs#545
---
 .../codegen/mxml/royale/MXMLRoyaleEmitter.java     | 98 ++++++++++++++++++----
 .../as/codegen/MXMLClassDirectiveProcessor.java    |  4 +
 .../internal/tree/mxml/MXMLXMLListNode.java        | 22 ++++-
 .../compiler/internal/tree/mxml/XMLBuilder.java    |  4 +-
 4 files changed, 110 insertions(+), 18 deletions(-)

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 67ca0cd..7e9747f 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
@@ -35,9 +35,13 @@ import java.util.Set;
 import java.util.Stack;
 
 import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.royale.abc.ABCConstants;
+import org.apache.royale.abc.instructionlist.InstructionList;
+import org.apache.royale.abc.semantics.Instruction;
 import org.apache.royale.abc.semantics.MethodInfo;
 import org.apache.royale.abc.semantics.Name;
 import org.apache.royale.abc.semantics.Namespace;
+import org.apache.royale.abc.semantics.OneOperandInstruction;
 import org.apache.royale.compiler.codegen.as.IASEmitter;
 import org.apache.royale.compiler.codegen.js.IJSEmitter;
 import org.apache.royale.compiler.codegen.js.IMappingEmitter;
@@ -1673,28 +1677,90 @@ public class MXMLRoyaleEmitter extends MXMLEmitter implements
     		parentNode = parentNode.getParent();
     	}
     	boolean isXML = parentNode instanceof IMXMLXMLNode;
+    	boolean isXMLList = parentNode instanceof IMXMLXMLListNode;
+    	String effectiveID = ((IMXMLInstanceNode)parentNode).getEffectiveID();
     	sb.append("this.");
-    	sb.append(((IMXMLInstanceNode)parentNode).getEffectiveID());
-    	while (nodeStack.size() > 0)
+    	sb.append(effectiveID);
+    	// at least for one XMLList case, we could not trust
+    	// the nodestack as children were only binding nodes
+    	// and not preceding XML nodes
+    	if (isXMLList)
     	{
-    		IASNode childNode = nodeStack.pop();
-    		int n = parentNode.getChildCount();
-    		int i = 0;
-    		for (; i < n; i++)
+    		// re-interpret the instruction list.
+    		// it would not be a surprise of the non-XMLList cases will
+    		// eventually require this code path
+    		InstructionListNode ilNode = (InstructionListNode)destNode.getExpressionNode();
+    		InstructionList il = ilNode.getInstructions();
+    		ArrayList<Instruction> abcs = il.getInstructions();
+    		int n = abcs.size();
+    		for (int i = 0; i < n; i++)
     		{
-    			if (childNode == parentNode.getChild(i))
-    				break;
-    		}
-    		assert i < n;
-    		sb.append("[" + new Integer(i).toString() + "]" );
-    		parentNode = childNode;
+    			Instruction inst = abcs.get(i);
+    			int opCode = inst.getOpcode();
+    			if (opCode == ABCConstants.OP_getlocal0)
+    			{
+    				if (i > 0)
+    					System.out.println("unexpected getLocal0 in binding expression");
+    			}
+    			else if (opCode == ABCConstants.OP_getproperty)
+    			{
+    				OneOperandInstruction getProp = (OneOperandInstruction)inst;
+    				Name propName = (Name)getProp.getOperand(0);
+    				if (i == 0)
+    					System.out.println("unexpected opcode in binding expression");
+    				else if (i == 1 && !propName.getBaseName().contentEquals(effectiveID))
+    					System.out.println("unexpected effectiveID in binding expression");
+    				else if (i > 1)
+    				{
+    					try
+    				    {
+    				        Integer.parseInt(propName.getBaseName());
+    			    		sb.append("[" + propName.getBaseName() + "]" );
+    				    } catch (NumberFormatException ex)
+    				    {
+    				    	sb.append(".elements(" + propName.getBaseName() + ")" );
+    				    }
+    				}
+    			}
+    			else if (opCode == ABCConstants.OP_getlocal1)
+    			{
+    				if (i != n - 3)
+    					System.out.println("unexpected getLocal1 in binding expression");    				
+    			}
+    			else if (opCode == ABCConstants.OP_setproperty)
+    			{
+    				if (i != n - 2)
+    					System.out.println("unexpected setProperty in binding expression");    				
+    				OneOperandInstruction setProp = (OneOperandInstruction)inst;
+    				Name propName = (Name)setProp.getOperand(0);
+    				if (!propName.getBaseName().contentEquals(destNode.getName()))
+    					System.out.println("unexpected setProperty name in binding expression");    				
+    				break; // exit loop
+    			}
+    		}    		
+	    	sb.append(".setAttribute('" + destNode.getName() + "', value);" );
     	}
-    	if (isXML)
+    	else
     	{
-    		sb.append(".setAttribute('" + destNode.getName() + "', value);" );
+	    	while (nodeStack.size() > 0)
+	    	{
+	    		IASNode childNode = nodeStack.pop();
+	    		int n = parentNode.getChildCount();
+	    		int i = 0;
+	    		for (; i < n; i++)
+	    		{
+	    			if (childNode == parentNode.getChild(i))
+	    				break;
+	    		}
+	    		assert i < n;
+	    		sb.append("[" + new Integer(i).toString() + "]" );
+	    		parentNode = childNode;
+	    	}
+	    	if (isXML)
+		    	sb.append(".setAttribute('" + destNode.getName() + "', value);" );
+	    	else
+	    		sb.append("." + destNode.getName() + " = value;");
     	}
-    	else
-    		sb.append("." + destNode.getName() + " = value;");
     	return sb.toString();
     }
 
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java
index 01adf85..a0a97ac 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java
@@ -5019,6 +5019,10 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor
         context.addInstruction(OP_findpropstrict, ABCGeneratingReducer.xmlListType);
         context.addInstruction(OP_pushstring, node.getXMLString());
         context.addInstruction(OP_constructprop, CONSTRUCT_XML_LIST_OPERANDS);
+        
+        // Traverse the children - these will be any MXMLBindingNode that were created for
+        // databinding expressions inside the XML
+        traverse(node, context);
     }
     
     /**
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLXMLListNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLXMLListNode.java
index 4e3fdb4..6764a36 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLXMLListNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLXMLListNode.java
@@ -25,10 +25,13 @@ import org.apache.royale.compiler.mxml.IMXMLTagData;
 import org.apache.royale.compiler.mxml.IMXMLTextData;
 import org.apache.royale.compiler.problems.MXMLXMLListMixedContentProblem;
 import org.apache.royale.compiler.tree.ASTNodeID;
+import org.apache.royale.compiler.tree.mxml.IMXMLBindingNode;
+import org.apache.royale.compiler.tree.mxml.IMXMLNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLXMLListNode;
 
 import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Implementation of the {@code IMXMLXMLListNode} interface.
@@ -54,6 +57,8 @@ class MXMLXMLListNode extends MXMLInstanceNode implements IMXMLXMLListNode
     private ArrayList<IMXMLTagData> childTags = new ArrayList<IMXMLTagData>();
 
     private String xmlString;
+    
+    private List<IMXMLBindingNode> bindings = new ArrayList<IMXMLBindingNode>();
 
     @Override
     public ASTNodeID getNodeID()
@@ -106,6 +111,17 @@ class MXMLXMLListNode extends MXMLInstanceNode implements IMXMLXMLListNode
 
         super.initializationComplete(builder, tag, info);
 
+        if (bindings.size() > 0)
+        {
+        	int childCount = getChildCount();
+        	List<IMXMLNode> children = new ArrayList<IMXMLNode>();
+        	for (int i = 0; i < childCount; i++)
+        	{
+        		children.add((IMXMLNode)getChild(i));
+        	}
+        	children.addAll(bindings);
+        	setChildren(children.toArray(new IMXMLNode[] {}));
+        }
         // don't pin the MXMLTagDatas
         childTags = null;
     }
@@ -115,7 +131,11 @@ class MXMLXMLListNode extends MXMLInstanceNode implements IMXMLXMLListNode
         StringWriter sw = new StringWriter();
         for (IMXMLTagData tag : childTags)
         {
-            new XMLBuilder(this, tag, tag.getCompositePrefixMap(), builder).processNode(tag, sw);
+        	IMXMLTagData parentTagData = tag.getParentTag();
+        	XMLBuilder xmlBuilder = new XMLBuilder(this, parentTagData, tag.getCompositePrefixMap(), builder);
+        	xmlBuilder.processNode(tag, sw);
+        	List<IMXMLBindingNode> bindings = xmlBuilder.getDatabindings();
+        	this.bindings.addAll(bindings);
         }
         xmlString = sw.toString();
     }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/XMLBuilder.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/XMLBuilder.java
index b428289..9b96951 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/XMLBuilder.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/XMLBuilder.java
@@ -444,7 +444,9 @@ class XMLBuilder
         }
         else
         {
-            il.addInstruction(ABCConstants.OP_getproperty, getNameForTag(tag));
+        	String rootTagName = rootTag.getName();
+        	if (!rootTagName.contentEquals("fx:XMLList"))
+        		il.addInstruction(ABCConstants.OP_getproperty, getNameForTag(tag));
             int index = getIndexOfTag(tag);
             il.addInstruction(ABCConstants.OP_getproperty, new Name(String.valueOf(index)));
         }