Updated Branches: refs/heads/develop b08d11d2f -> a5c3a4fee
changes to get BasicTests to run with new MXML and Databinding codegen Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/a5c3a4fe Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/a5c3a4fe Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/a5c3a4fe Branch: refs/heads/develop Commit: a5c3a4fee02461ab35d1d93c2c6f1f6eeeb65a30 Parents: b08d11d Author: Alex Harui <[email protected]> Authored: Thu Oct 31 10:43:36 2013 -0700 Committer: Alex Harui <[email protected]> Committed: Thu Oct 31 10:43:36 2013 -0700 ---------------------------------------------------------------------- .../as/codegen/MXMLClassDirectiveProcessor.java | 451 +++++++++++++++---- .../databinding/BindingCodeGenUtils.java | 2 +- .../databinding/MXMLBindingDirectiveHelper.java | 39 +- .../compiler/internal/projects/FlexProject.java | 9 +- .../internal/targets/FlexAppSWFTarget.java | 5 + .../flex/compiler/mxml/IMXMLTypeConstants.java | 4 + 6 files changed, 421 insertions(+), 89 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java b/compiler/src/org/apache/flex/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java index a868416..a344b32 100644 --- a/compiler/src/org/apache/flex/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java +++ b/compiler/src/org/apache/flex/compiler/internal/as/codegen/MXMLClassDirectiveProcessor.java @@ -20,6 +20,7 @@ package org.apache.flex.compiler.internal.as.codegen; import static org.apache.flex.abc.ABCConstants.CONSTANT_Qname; import static org.apache.flex.abc.ABCConstants.OP_applytype; +import static org.apache.flex.abc.ABCConstants.OP_call; import static org.apache.flex.abc.ABCConstants.OP_callproperty; import static org.apache.flex.abc.ABCConstants.OP_callpropvoid; import static org.apache.flex.abc.ABCConstants.OP_callsupervoid; @@ -29,6 +30,7 @@ import static org.apache.flex.abc.ABCConstants.OP_constructsuper; import static org.apache.flex.abc.ABCConstants.OP_dup; import static org.apache.flex.abc.ABCConstants.OP_finddef; import static org.apache.flex.abc.ABCConstants.OP_findpropstrict; +import static org.apache.flex.abc.ABCConstants.OP_getglobalscope; import static org.apache.flex.abc.ABCConstants.OP_getlex; import static org.apache.flex.abc.ABCConstants.OP_getlocal0; import static org.apache.flex.abc.ABCConstants.OP_getlocal1; @@ -134,6 +136,7 @@ import org.apache.flex.compiler.definitions.references.IReference; import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference; import org.apache.flex.compiler.definitions.references.ReferenceFactory; import org.apache.flex.compiler.exceptions.CodegenInterruptedException; +import org.apache.flex.compiler.internal.abc.FunctionGeneratorHelper; import org.apache.flex.compiler.internal.caches.CSSDocumentCache; import org.apache.flex.compiler.internal.codegen.databinding.MXMLBindingDirectiveHelper; import org.apache.flex.compiler.internal.css.codegen.CSSCompilationSession; @@ -142,12 +145,14 @@ import org.apache.flex.compiler.internal.css.codegen.CSSEmitter; import org.apache.flex.compiler.internal.definitions.ClassDefinition; import org.apache.flex.compiler.internal.definitions.DefinitionBase; import org.apache.flex.compiler.internal.definitions.EventDefinition; +import org.apache.flex.compiler.internal.definitions.FunctionDefinition; import org.apache.flex.compiler.internal.definitions.NamespaceDefinition; import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase; import org.apache.flex.compiler.internal.projects.FlexProject; import org.apache.flex.compiler.internal.resourcebundles.ResourceBundleUtils; import org.apache.flex.compiler.internal.scopes.ASProjectScope; import org.apache.flex.compiler.internal.scopes.ASScope; +import org.apache.flex.compiler.internal.semantics.SemanticUtils; import org.apache.flex.compiler.internal.tree.as.NodeBase; import org.apache.flex.compiler.internal.tree.as.VariableNode; import org.apache.flex.compiler.mxml.IMXMLLanguageConstants; @@ -264,6 +269,18 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor private static final String EVENT_HANDLER_NAME_BASE = ">"; /** + * Autogenerated vector generator methods are named >v0, >v1, etc. + * Using short names, and using the same names in each MXML document, + * decreases SWF size. + * Using a character that is not legal in ActionScript identifiers + * means that even if the event handler must be public + * (because it is referenced in a descriptor) + * the name will not collide with the name of a developer-written + * method and cannot be accessed from developer code. + */ + private static final String VECTOR_GENERATOR_NAME_BASE = ">v"; + + /** * Autogenerated instance initialization methods are named i0, i1, etc. */ private static final String INSTANCE_INITIALIZER_NAME_BASE = "i"; @@ -371,6 +388,42 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor /** * Creates a MethodInfo describing the signature for an autogenerated + * vector generator method. + * @param vectorNode - a node, which is used to determine + * the type of the 'vector'. + * @param handlerName - the name for the autogenerated event handler method. + * @return The MethodInfo specifying the signature of the vector generator method. + */ + public static MethodInfo createVectorGeneratorMethodInfo(ICompilerProject project, + IMXMLVectorNode vectorNode, + String handlerName) + { + MethodInfo mi = new MethodInfo(); + + mi.setMethodName(handlerName); + + ITypeDefinition type = vectorNode.getType(); + Name typeName = ((TypeDefinitionBase)type).getMName(project); + + Vector<Name> paramTypes = new Vector<Name>(); + paramTypes.add(IMXMLTypeConstants.NAME_ARRAY); + mi.setParamTypes(paramTypes); + + Vector<String> paramName = new Vector<String>(); + paramName.add("array"); + mi.setParamNames(paramName); + + // TODO: Allow these MXML nodes to use registers. + mi.setFlags(mi.getFlags() | ABCConstants.NEED_ACTIVATION); + + // Event handlers return void. + mi.setReturnType(typeName); + + return mi; + } + + /** + * Creates a MethodInfo describing the signature for an autogenerated * MXML instance initializer corresponding to an MXMLInstanceNode. * Instance initializers have no parameters, and their return type * is the type of the instance that they create. @@ -424,6 +477,12 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor private int eventHandlerCounter = 0; /** + * An incrementing counter used to create the names of the + * auto-generated vector generator methods. + */ + private int vectorGeneratorCounter = 0; + + /** * We delegate much of the work for databindings down to this guy */ private final MXMLBindingDirectiveHelper bindingDirectiveHelper = new MXMLBindingDirectiveHelper(this, emitter); @@ -470,6 +529,21 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor new HashMap<IMXMLEventSpecifierNode, Name>(); /** + * A Map mapping an vector type to the Name of the vector "generator" + * method (>v0, >v1, etc.) associated with that node. + * <p> + * The handler method may or may not exist at the time + * that the handler name is assigned to the event node. + * For example, when a State tag appears before + * an instance tag with a state-dependent event, + * the name will get assigned and the code generated later. + * <p> + * This map is managed ONLY by getVectorGeneratorName(). + */ + private final Map<Name, Name> VectorGeneratorMap = + new HashMap<Name, Name>(); + + /** * This flag keeps track of whether there were styles * specified on the class definition tag. * <p> @@ -660,6 +734,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor Context stateContext = new Context((IMXMLInstanceNode)node, il); stateContext.isContentFactory = true; processNode(node, stateContext); + stateContext.transfer(IL.MXML_CONTENT_FACTORY); stateContext.addInstruction(OP_newarray, stateContext.getCounter(IL.MXML_CONTENT_FACTORY)); } else @@ -1109,7 +1184,21 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor // call the Binding helper to get all the data binding setup code addBindingCodeForCtor(ctor_insns); - + + // add call to MXMLAttributes + if (getProject().getTargetSettings().getMxmlChildrenAsData()) + { + // generateMXMLAttributes(attributes); + FunctionDefinition funcDef = (FunctionDefinition)SemanticUtils.findProperty(classDefinition.getContainedScope(), + "generateMXMLAttributes", + getProject(), false); + Name funcName = ((FunctionDefinition)funcDef).getMName(getProject()); + ctor_insns.addInstruction(OP_getlocal0); + ctor_insns.addInstruction(OP_findpropstrict, NAME_MXML_PROPERTIES_GETTER); + ctor_insns.addInstruction(OP_getproperty, NAME_MXML_PROPERTIES_GETTER); + ctor_insns.addInstruction(OP_callpropvoid, new Object[] {funcName, 1 }); + } + ctor_insns.addInstruction(OP_returnvoid); mbv.visit(); @@ -2035,6 +2124,33 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor } /** + * Determines the Name of the event handler method for an event node. + * This can get called to preassign the name before the method gets generated. + */ + public Name getVectorGeneratorName(Name typeName) + { + // Check the map to see if a handler name + // has already been assigned to this event node. + Name name = VectorGeneratorMap.get(typeName); + + // If so, return it. + if (name != null) + return name; + + // Otherwise, generate the next one in the sequence ">v1", ">v1", etc. + String baseName = VECTOR_GENERATOR_NAME_BASE + vectorGeneratorCounter++; + + // Either make the Name public or put it in the special + // private namespace for APIs that are autogenerated. + name = createMXMLPrivateName(baseName); + + // Remember it in the map. + VectorGeneratorMap.put(typeName, name); + + return name; + } + + /** * Determines whether a node is state-dependent. * TODO: we should move to IMXMLNode */ @@ -2273,7 +2389,8 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor // try to determine if this is the children of an MX Container boolean isMXMLDisplayObjectChild = node.getNodeID() == ASTNodeID.MXMLInstanceID && - node.getParent().getNodeID() == ASTNodeID.MXMLInstanceID; + (node.getParent().getNodeID() == ASTNodeID.MXMLInstanceID || + node.getParent().getNodeID() == ASTNodeID.MXMLDocumentID); if (isMXMLDisplayObjectChild) { // if it is, build up the children in this instruction list @@ -2501,8 +2618,10 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor return n == null || isDataBindingNode(n); } - boolean isChildrenAsDataCodeGen(IMXMLExpressionNode node) + boolean isChildrenAsDataCodeGen(IMXMLExpressionNode node, Context context) { + if (context.parentContext.makingSimpleArray) return false; + return (getProject().getTargetSettings().getMxmlChildrenAsData() && (node.getParent().getNodeID() == ASTNodeID.MXMLPropertySpecifierID || node.getParent().getNodeID() == ASTNodeID.MXMLStyleSpecifierID)); @@ -2517,7 +2636,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLBoolean(IMXMLBooleanNode booleanNode, Context context) { - if (isChildrenAsDataCodeGen(booleanNode)) + if (isChildrenAsDataCodeGen(booleanNode, context)) context.addInstruction(OP_pushtrue); // simple type boolean value = isDataBound(booleanNode) ? false : booleanNode.getValue(); @@ -2535,7 +2654,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLInt(IMXMLIntNode intNode, Context context) { - if (isChildrenAsDataCodeGen(intNode)) + if (isChildrenAsDataCodeGen(intNode, context)) context.addInstruction(OP_pushtrue); // simple type int value = isDataBound(intNode) ? 0 : intNode.getValue(); @@ -2552,7 +2671,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLUint(IMXMLUintNode uintNode, Context context) { - if (isChildrenAsDataCodeGen(uintNode)) + if (isChildrenAsDataCodeGen(uintNode, context)) context.addInstruction(OP_pushtrue); // simple type long value = isDataBound(uintNode) ? 0 : uintNode.getValue(); @@ -2569,7 +2688,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLNumber(IMXMLNumberNode numberNode, Context context) { - if (isChildrenAsDataCodeGen(numberNode)) + if (isChildrenAsDataCodeGen(numberNode, context)) context.addInstruction(OP_pushtrue); // simple type double value = isDataBound(numberNode) ? Double.NaN : numberNode.getValue(); @@ -2586,7 +2705,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLString(IMXMLStringNode stringNode, Context context) { - if (isChildrenAsDataCodeGen(stringNode)) + if (isChildrenAsDataCodeGen(stringNode, context)) context.addInstruction(OP_pushtrue); // simple type String value = isDataBound(stringNode) ? null : stringNode.getValue(); @@ -2612,7 +2731,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor if (isDataBindingNode(classNode)) return; - if (isChildrenAsDataCodeGen(classNode)) + if (isChildrenAsDataCodeGen(classNode, context)) context.addInstruction(OP_pushtrue); // simple type IExpressionNode expressionNode = (IExpressionNode)classNode.getExpressionNode(); @@ -2643,7 +2762,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor if (isDataBindingNode(functionNode)) return; - if (isChildrenAsDataCodeGen(functionNode)) + if (isChildrenAsDataCodeGen(functionNode, context)) context.addInstruction(OP_pushtrue); // simple type IExpressionNode expressionNode = (IExpressionNode)functionNode.getExpressionNode(); @@ -2732,9 +2851,12 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor emitDesignLayerInstance(node, designLayerInstanceContext); endContext(node, designLayerInstanceContext, context); - // The DesignLayer object will not be added to the parent object, so it - // need to be removed from the stack. - context.mainInstructionList.addInstruction(ABCConstants.OP_pop); + if (!getProject().getTargetSettings().getMxmlChildrenAsData()) + { + // The DesignLayer object will not be added to the parent object, so it + // need to be removed from the stack. + context.mainInstructionList.addInstruction(ABCConstants.OP_pop); + } } /** @@ -2763,31 +2885,49 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ private void emitDesignLayerInstance(IMXMLDesignLayerNode node, Context context) { + boolean newCodeGen = getProject().getTargetSettings().getMxmlChildrenAsData(); + traverse(node, context, MXML_SPECIFIER_NODES); // Construct DesignLayer instance in the context's mainInstructionList. final Name instanceClassName = context.instanceClassName; context.addInstruction(OP_findpropstrict, instanceClassName); context.addInstruction(OP_constructprop, new Object[] {instanceClassName, 0}); - setSpecifiers(context); - callInitialized(node, context); - - for (int i = 0; i < node.getChildCount(); i++) + int numElements = setSpecifiers(context, newCodeGen, false); + numElements++; // for pushing the class + if (!newCodeGen) { - final IASNode child = node.getChild(i); - if (child instanceof IMXMLDesignLayerNode) + callInitialized(node, context); + + for (int i = 0; i < node.getChildCount(); i++) { - // Call temp.addLayer(child) if there's a DesignLayer node in the direct children. - final IMXMLDesignLayerNode designLayerChildNode = (IMXMLDesignLayerNode)child; - if (!designLayerChildNode.skipCodeGeneration()) - callAddLayer(node, context, designLayerChildNode); + final IASNode child = node.getChild(i); + if (child instanceof IMXMLDesignLayerNode) + { + // Call temp.addLayer(child) if there's a DesignLayer node in the direct children. + final IMXMLDesignLayerNode designLayerChildNode = (IMXMLDesignLayerNode)child; + if (!designLayerChildNode.skipCodeGeneration()) + callAddLayer(node, context, designLayerChildNode); + } + else if (child instanceof IMXMLInstanceNode) + { + // Set directInstanceChild.designLayer = designLayer. + final IMXMLInstanceNode instanceChildNode = (IMXMLInstanceNode)child; + setDesignLayer(node, context, instanceChildNode); + } } - else if (child instanceof IMXMLInstanceNode) + } + else + { + if (context.parentContext.isContentFactory) + context.parentContext.incrementCounter(IL.MXML_CONTENT_FACTORY, numElements); + else if (!context.parentContext.isContentFactory) { - // Set directInstanceChild.designLayer = designLayer. - final IMXMLInstanceNode instanceChildNode = (IMXMLInstanceNode)child; - setDesignLayer(node, context, instanceChildNode); - } + if (context.parentContext.makingArrayValues) + context.parentContext.numArrayValues += numElements; + else + context.addInstruction(OP_newarray, numElements); // if not in content factory, create the array now + } } } @@ -2840,12 +2980,47 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLObject(IMXMLObjectNode objectNode, Context context) { + boolean newCodeGen = getProject().getTargetSettings().getMxmlChildrenAsData(); + + context.makingSimpleArray = context.parentContext.makingSimpleArray; + + if (newCodeGen && !context.makingSimpleArray) + { + context.addInstruction(OP_findpropstrict, IMXMLTypeConstants.NAME_OBJECT); + context.addInstruction(OP_getproperty, IMXMLTypeConstants.NAME_OBJECT); + } traverse(objectNode, context); + int numElements = context.getCounter(IL.PROPERTIES); + if (newCodeGen && !context.makingSimpleArray) + context.pushNumericConstant(numElements); context.transfer(IL.PROPERTIES); - int n = objectNode.getChildCount(); - context.addInstruction(OP_newobject, n); + if (!newCodeGen || context.makingSimpleArray) + { + int n = objectNode.getChildCount(); + context.addInstruction(OP_newobject, n); + } + else + { + context.pushNumericConstant(context.getCounter(IL.STYLES)); + context.pushNumericConstant(context.getCounter(IL.EFFECT_STYLES)); + context.pushNumericConstant(context.getCounter(IL.EVENTS)); + context.addInstruction(OP_pushnull); // no children + numElements *= 3; // 3 entries per property + numElements += 6; + + if (context.parentContext.isContentFactory) + context.parentContext.incrementCounter(IL.MXML_CONTENT_FACTORY, numElements); + else if (!context.parentContext.isContentFactory) + { + if (context.parentContext.makingArrayValues) + context.parentContext.numArrayValues += numElements; + else + context.addInstruction(OP_newarray, numElements); // if not in content factory, create the array now + } + + } } /** @@ -2868,16 +3043,15 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLArray(IMXMLArrayNode arrayNode, Context context) { + boolean isSimple = true; if (getProject().getTargetSettings().getMxmlChildrenAsData()) { if (!context.isContentFactory) { if (context.parentContext.isStateDescriptor) context.addInstruction(OP_pushnull); // array of descriptors - else - { - boolean isSimple = true; - + else if (!context.parentContext.makingSimpleArray) + { for (int i = 0; i < arrayNode.getChildCount(); i++) { final IASNode child = arrayNode.getChild(i); @@ -2889,6 +3063,7 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor } } context.makingArrayValues = true; + context.makingSimpleArray = isSimple; context.addInstruction(isSimple ? OP_pushtrue : OP_pushnull); // arrays are simple values } } @@ -2929,7 +3104,10 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor } else if (context.makingArrayValues) { - context.addInstruction(OP_newarray, context.numArrayValues); + if (isSimple) + context.addInstruction(OP_newarray, nMax); + else + context.addInstruction(OP_newarray, context.numArrayValues); return; } } @@ -2988,6 +3166,47 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor /** * Generates instructions in the current context + * to set an event handler specified by an {@code IMXMLEventSpecifierNode}. + * <p> + * This is accomplished by generating a call to <code>addEventListener()</code> + * on the target. + */ + Name generateVectorGenerator(Name typeName, IMXMLVectorNode vectorNode) + { + // Event nodes (including state-dependent ones) + // generate a new event handler method. + // Create a MethodInfo and a method trait for the handler. + Name name = getVectorGeneratorName(typeName); + MethodInfo methodInfo = createVectorGeneratorMethodInfo( + getProject(), vectorNode, name.getBaseName()); + addMethodTrait(name, methodInfo, false); + + ICompilerProject project = getProject(); + ASProjectScope projectScope = (ASProjectScope)project.getScope(); + IDefinition vectorDef = projectScope.findDefinitionByName(IASLanguageConstants.Vector_qname); + Name vectorName = ((ClassDefinition)vectorDef).getMName(project); + + InstructionList generatorFunctionBody = new InstructionList(); + generatorFunctionBody.addInstruction(OP_getlocal0); + generatorFunctionBody.addInstruction(OP_pushscope); + // Synthesize the class Vector.<T>. + generatorFunctionBody.addInstruction(OP_getlex, vectorName); + generatorFunctionBody.addInstruction(OP_getlex, typeName); + generatorFunctionBody.addInstruction(OP_applytype, 1); + generatorFunctionBody.addInstruction(OP_getglobalscope); + generatorFunctionBody.addInstruction(OP_getlocal1); + generatorFunctionBody.addInstruction(OP_call, 1); + generatorFunctionBody.addInstruction(OP_returnvalue); + + + // now generate the function + FunctionGeneratorHelper.generateFunction(emitter, methodInfo, generatorFunctionBody); + + return name; + } + + /** + * Generates instructions in the current context * to push the value of an {@code IMXMLVectorNode}. * <p> * First this method creates the synthetic Vector.<T> type @@ -3011,6 +3230,9 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor */ void processMXMLVector(IMXMLVectorNode vectorNode, Context context) { + if (getProject().getTargetSettings().getMxmlChildrenAsData()) + context.addInstruction(OP_pushundefined); // vector type + ICompilerProject project = getProject(); int n = vectorNode.getChildCount(); ITypeDefinition type = vectorNode.getType(); @@ -3025,38 +3247,64 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor Nsset nsSet = new Nsset(new Namespace(ABCConstants.CONSTANT_PackageNs)); Name indexName = new Name(ABCConstants.CONSTANT_MultinameL, nsSet, null); - // Synthesize the class Vector.<T>. - context.addInstruction(OP_getlex, vectorName); - context.addInstruction(OP_getlex, typeName); - context.addInstruction(OP_applytype, 1); - - // Call the Vector.<T> constructor with 1 or two arguments. - // The first is the number of elements. - // The second is 'fixed', which defaults to false. - context.pushNumericConstant(n); - if (fixed) - context.addInstruction(OP_pushtrue); - context.addInstruction(OP_construct, fixed ? 2 : 1); - - // Set each element of the vector. - for (int i = 0; i < n; i++) + if (getProject().getTargetSettings().getMxmlChildrenAsData()) { - // Push the vector instance whose element we're setting. - context.addInstruction(OP_dup); - - // Push the index of the element we're setting. - context.pushNumericConstant(i); + context.addInstruction(OP_getlex, typeName); // push the type so decoders have a hint + Name vectorGenerator = generateVectorGenerator(typeName, vectorNode); + context.addInstruction(OP_getlocal0); + context.addInstruction(OP_getproperty, vectorGenerator); - // Push the value of the element we're setting. - // Note: Here we call processNode() on each child, - // rather than calling traverse(), because we need to emit - // code before and after each element value push. - IMXMLInstanceNode elementNode = (IMXMLInstanceNode)vectorNode.getChild(i); - processNode(elementNode, context); + context.makingArrayValues = true; + // Set each element of the vector. + for (int i = 0; i < n; i++) + { + // Push the value of the element we're setting. + // Note: Here we call processNode() on each child, + // rather than calling traverse(), because we need to emit + // code before and after each element value push. + IMXMLInstanceNode elementNode = (IMXMLInstanceNode)vectorNode.getChild(i); + processNode(elementNode, context); + + } + // the type hint and conversion function add 2 + context.addInstruction(OP_newarray, context.numArrayValues + 2); + context.makingArrayValues = false; + } + else + { + // Synthesize the class Vector.<T>. + context.addInstruction(OP_getlex, vectorName); + context.addInstruction(OP_getlex, typeName); + context.addInstruction(OP_applytype, 1); - // Set the element to the value. - // This will pop the previous three values. - context.addInstruction(OP_setproperty, indexName); + // Call the Vector.<T> constructor with 1 or two arguments. + // The first is the number of elements. + // The second is 'fixed', which defaults to false. + context.pushNumericConstant(n); + if (fixed) + context.addInstruction(OP_pushtrue); + context.addInstruction(OP_construct, fixed ? 2 : 1); + + // Set each element of the vector. + for (int i = 0; i < n; i++) + { + // Push the vector instance whose element we're setting. + context.addInstruction(OP_dup); + + // Push the index of the element we're setting. + context.pushNumericConstant(i); + + // Push the value of the element we're setting. + // Note: Here we call processNode() on each child, + // rather than calling traverse(), because we need to emit + // code before and after each element value push. + IMXMLInstanceNode elementNode = (IMXMLInstanceNode)vectorNode.getChild(i); + processNode(elementNode, context); + + // Set the element to the value. + // This will pop the previous three values. + context.addInstruction(OP_setproperty, indexName); + } } } @@ -3129,7 +3377,9 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor // if not in content factory, create the array now // this is for an ArrayList as the dataProvider - setDocument(instanceNode, false, context); + // AJH: maybe we shouldn't call setDocument at all + if (!getProject().getTargetSettings().getMxmlChildrenAsData()) + setDocument(instanceNode, false, context); // Sets the id property if the instance // implements IDeferredInstantiationUIComponent. @@ -3563,9 +3813,11 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor if (styleNode.getParent() instanceof IMXMLClassDefinitionNode) { context.startUsing(IL.MODULE_FACTORY_STYLES); + context.makingSimpleArray = true; setFactoryStyle(styleNode, context); + context.makingSimpleArray = false; context.stopUsing(IL.MODULE_FACTORY_STYLES, 1); hasStyleSpecifiers = true; @@ -3573,11 +3825,32 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor else if (generateDescriptorCode(styleNode, context)) { - context.startUsing(IL.DESCRIPTOR_STYLES); - - setFactoryStyle(styleNode, context); - - context.stopUsing(IL.DESCRIPTOR_STYLES, 1); + if (!getProject().getTargetSettings().getMxmlChildrenAsData()) + { + context.startUsing(IL.DESCRIPTOR_STYLES); + + setFactoryStyle(styleNode, context); + + context.stopUsing(IL.DESCRIPTOR_STYLES, 1); + } + else + { + context.startUsing(IL.STYLES); + + String styleName = styleNode.getName(); + + // Push the first argument: the name of the style. + context.addInstruction(OP_pushstring, styleName); + + context.isContentFactory = false; + + // Push the second argument: the value of the style. + // Do this by codegen'ing sole child, which is an IMXMLInstanceNode. + traverse(styleNode, context); + + context.stopUsing(IL.STYLES, 1); + + } } else if (generateNonDescriptorCode(styleNode, context)) @@ -3739,13 +4012,29 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor if (generateDescriptorCode(eventNode, context)) { - context.startUsing(IL.DESCRIPTOR_EVENTS); - - context.addInstruction(OP_pushstring, eventName); - - context.addInstruction(OP_pushstring, eventHandler.getBaseName()); - - context.stopUsing(IL.DESCRIPTOR_EVENTS, 1); + if (getProject().getTargetSettings().getMxmlChildrenAsData()) + { + context.startUsing(IL.EVENTS); + + // Push the first argument: the name of the event (e.g., "click"). + context.addInstruction(OP_pushstring, eventName); + + // Push the second argument: the handler reference (e.g., >0). + context.addInstruction(OP_getlocal0); + context.addInstruction(OP_getproperty, eventHandler); + + context.stopUsing(IL.EVENTS, 1); + } + else + { + context.startUsing(IL.DESCRIPTOR_EVENTS); + + context.addInstruction(OP_pushstring, eventName); + + context.addInstruction(OP_pushstring, eventHandler.getBaseName()); + + context.stopUsing(IL.DESCRIPTOR_EVENTS, 1); + } } if (generateNonDescriptorCode(eventNode, context)) @@ -5010,6 +5299,14 @@ public class MXMLClassDirectiveProcessor extends ClassDirectiveProcessor boolean hasBeads; /** + * This flag is true when setting styles + * in a style factory or making other + * simple arrays that don't have instances + * as values. + */ + boolean makingSimpleArray; + + /** * This flag is true when setting values * in an array (other than contextFactory) */ http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingCodeGenUtils.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingCodeGenUtils.java b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingCodeGenUtils.java index 7b27329..296a81b 100644 --- a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingCodeGenUtils.java +++ b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingCodeGenUtils.java @@ -450,7 +450,7 @@ public class BindingCodeGenUtils // version 2: just throw - private static void makeParameterFunction(IABCVisitor emitter, InstructionList ret, IExpressionNode[] params) + public static void makeParameterFunction(IABCVisitor emitter, InstructionList ret, IExpressionNode[] params) { //----------- step 1: build up a method info for the function http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java index 1054c40..7d7d41d 100644 --- a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java +++ b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java @@ -40,11 +40,13 @@ import org.apache.flex.compiler.internal.as.codegen.MXMLClassDirectiveProcessor; import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType; import org.apache.flex.compiler.internal.projects.FlexProject; import org.apache.flex.compiler.internal.scopes.ASScope; +import org.apache.flex.compiler.internal.targets.FlexAppSWFTarget; import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAsNode; import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; import org.apache.flex.compiler.internal.tree.as.IdentifierNode; import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode; import org.apache.flex.compiler.mxml.IMXMLTypeConstants; +import org.apache.flex.compiler.targets.ISWFTarget; import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.tree.as.IExpressionNode; import org.apache.flex.compiler.tree.mxml.IMXMLBindingNode; @@ -149,13 +151,24 @@ public class MXMLBindingDirectiveHelper // Just comment it out before checking //System.out.println("db: " + bindingDataBase); + boolean isFlexSDK = false; + ISWFTarget target = host.getProject().getSWFTarget(); + if (target instanceof FlexAppSWFTarget) + { + if (!((FlexAppSWFTarget)target).isFlexInfo()) + { + makeSpecialMemberVariablesForBinding(); + isFlexSDK = true; + } + else + host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE); + } + if (host.getProject().getTargetSettings().getMxmlChildrenAsData()) - return outputBindingInfoAsData(); + return outputBindingInfoAsData(isFlexSDK); InstructionList ret = new InstructionList(); - - makeSpecialMemberVariablesForBinding(); - + makePropertyGetterIfNeeded(); ret.addAll(makeBindingsAndGetters()); @@ -167,10 +180,9 @@ public class MXMLBindingDirectiveHelper return ret; } - private InstructionList outputBindingInfoAsData() + private InstructionList outputBindingInfoAsData(boolean isFlexSDK) { System.out.println("outputBindingInfoAsData"); - host.addVariableTrait(IMXMLTypeConstants.NAME_BINDINGS, NAME_ARRAYTYPE); InstructionList ret = new InstructionList(); int propertyCount = 0; @@ -185,14 +197,14 @@ public class MXMLBindingDirectiveHelper s = bi.getSourceString(); if (s == null) s = getSourceStringFromGetter(bi.getExpressionNodesForGetter()); - if (s.contains(".")) + if (s.contains(".") && !isFlexSDK) { String[] parts = s.split("\\."); for (String part : parts) ret.addInstruction(OP_pushstring, part); ret.addInstruction(OP_newarray, parts.length); } - else if (s == null || s.length() == 0) + else if (s == null || s.length() == 0 || isFlexSDK) { BindingCodeGenUtils.generateGetter(emitter, ret, bi.getExpressionNodesForGetter(), host.getInstanceScope()); } @@ -231,6 +243,12 @@ public class MXMLBindingDirectiveHelper ret.addInstruction(OP_swap); // stack : bindings, this ret.addInstruction(OP_setproperty, IMXMLTypeConstants.NAME_BINDINGS); + + if (isFlexSDK) + { + ret.addInstruction(OP_getlocal0); + ret.addInstruction(OP_callpropvoid, IMXMLTypeConstants.ARG_SETUPBINDINGS); + } return ret; } @@ -247,9 +265,12 @@ public class MXMLBindingDirectiveHelper FunctionWatcherInfo functionWatcherInfo = (FunctionWatcherInfo)watcherInfoBase; ret.addInstruction(OP_pushstring, functionWatcherInfo.getFunctionName()); + InstructionList paramFunction = new InstructionList(); + BindingCodeGenUtils.makeParameterFunction(emitter, paramFunction, functionWatcherInfo.params); + ret.addAll(paramFunction); outputEventNames(ret, functionWatcherInfo.getEventNames()); outputBindings(ret, functionWatcherInfo.getBindings()); - propertyCount += 4; + propertyCount += 5; } else if ((type == WatcherType.STATIC_PROPERTY) || (type == WatcherType.PROPERTY)) { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java b/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java index 2b525b9..69f0bff 100644 --- a/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java +++ b/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java @@ -508,13 +508,18 @@ public class FlexProject extends ASProject implements IFlexProject targetSettings = value; } + private ISWFTarget target; + + public ISWFTarget getSWFTarget() + { + return target; + } + @Override public ISWFTarget createSWFTarget(ITargetSettings targetSettings, ITargetProgressMonitor progressMonitor) throws InterruptedException { this.targetSettings = targetSettings; - ISWFTarget target; - if (isFlex()) { String rootClassName = targetSettings.getRootClassName(); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/internal/targets/FlexAppSWFTarget.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/targets/FlexAppSWFTarget.java b/compiler/src/org/apache/flex/compiler/internal/targets/FlexAppSWFTarget.java index e1993ef..8a2afeb 100644 --- a/compiler/src/org/apache/flex/compiler/internal/targets/FlexAppSWFTarget.java +++ b/compiler/src/org/apache/flex/compiler/internal/targets/FlexAppSWFTarget.java @@ -127,6 +127,11 @@ public class FlexAppSWFTarget extends AppSWFTarget private final FlexProject flexProject; + public boolean isFlexInfo() + { + return getDelegate().isFlexInfo(getRootClassDefinition()); + } + private FlexDelegate delegate; private FlexDelegate getDelegate() http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a5c3a4fe/compiler/src/org/apache/flex/compiler/mxml/IMXMLTypeConstants.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/mxml/IMXMLTypeConstants.java b/compiler/src/org/apache/flex/compiler/mxml/IMXMLTypeConstants.java index 59b7203..a93bf9b 100644 --- a/compiler/src/org/apache/flex/compiler/mxml/IMXMLTypeConstants.java +++ b/compiler/src/org/apache/flex/compiler/mxml/IMXMLTypeConstants.java @@ -175,10 +175,13 @@ public interface IMXMLTypeConstants // I can't get Flex to work when I use attempt to use mx_internal // It almost works, but something in the M7 test app doens't quite work... + // AJH: 10/30/13 BindingManager is using hasOwnProperty(_bindingsByDestination) + // which I don't think works with mx_internal //public final Name NAME_WATCHERS = new Name (NAMESPACE_MX_INTERNAL,"_watchers"); // member variable of component with bindings //public final Name NAME_BINDINGS = new Name (NAMESPACE_MX_INTERNAL,"_bindings"); // member variable of component with bindings //public final Name NAME_BINDINGSBYDESTINATION = new Name(NAMESPACE_MX_INTERNAL,"_bindingsByDestination"); // member variable of component with bindings //public final Name NAME_BINDINGSBEGINWITHWORD = new Name(NAMESPACE_MX_INTERNAL,"_bindingsBeginWithWord"); // member variable of component with bindings + public final Name NAME_SETUPBINDINGS = new Name(NAMESPACE_MX_INTERNAL,"setupBindings"); // member function of component with bindings public final Name NAME_WATCHERS = new Name("_watchers"); // member variable of component with bindings public final Name NAME_BINDINGS = new Name("_bindings"); // member variable of component with bindings @@ -193,6 +196,7 @@ public interface IMXMLTypeConstants new Name("updateParent"), 1}; public final Object[] ARG_ADDCHILD = new Object[] {new Name("addChild"), 1}; public final Object[] ARG_EXECUTE = new Object[] {NAME_EXECUTE, 0}; + public final Object[] ARG_SETUPBINDINGS = new Object[] {NAME_SETUPBINDINGS, 0}; // this is a "Name" to use for the property "array index" public final Name NAME_ARRAYINDEXPROP = new Name(ABCConstants.CONSTANT_MultinameL, new Nsset(new Namespace(CONSTANT_PackageNs)), null);
