This is an automated email from the ASF dual-hosted git repository.
joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
The following commit(s) were added to refs/heads/develop by this push:
new a05d8400c MXMLRoyaleEmitter: Added support for
mx.core.UIComponentDescriptor with -children-as-data=false for JavaScript
a05d8400c is described below
commit a05d8400c466da4bebebb04e0f99415e14c3a5ab
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed Apr 1 11:27:36 2026 -0700
MXMLRoyaleEmitter: Added support for mx.core.UIComponentDescriptor with
-children-as-data=false for JavaScript
---
RELEASE_NOTES.md | 1 +
.../codegen/mxml/royale/MXMLRoyaleEmitter.java | 279 ++++++++++++++++++++-
2 files changed, 278 insertions(+), 2 deletions(-)
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index e6b46b5bc..3a3a5b06d 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -74,6 +74,7 @@ Apache Royale Compiler 1.0.0
- compiler: Fixed `mx.core.DeferredInstanceFromFunction` not getting emitted
when targeting JavaScript.
- compiler: Fixed intermittent missing `goog.require()` calls when using JS
target.
- compiler: Added support for `mx.core.IDeferredInstance` for default
properties with `-children-as-data=false` for JavaScript.
+- compiler: Added support for `mx.core.UIComponentDescriptor` for components
that are containers.
- debugger: Added missing isolate ID to SWF load and unload events.
- debugger: Fixed debugger targeting the current JDK version instead of the
intended minimum JDK version.
- debugger: Fixed localized messages appearing as unprocessed tokens.
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 320cbf4a8..b9d347699 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
@@ -25,6 +25,7 @@ import java.io.FilterWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -93,6 +94,7 @@ import
org.apache.royale.compiler.internal.tree.mxml.MXMLDocumentNode;
import org.apache.royale.compiler.internal.tree.mxml.MXMLFileNode;
import org.apache.royale.compiler.internal.tree.mxml.MXMLBindingNode;
import org.apache.royale.compiler.mxml.IMXMLLanguageConstants;
+import org.apache.royale.compiler.mxml.IMXMLTypeConstants;
import org.apache.royale.compiler.problems.FileNotFoundProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.projects.IRoyaleProject;
@@ -902,6 +904,8 @@ public class MXMLRoyaleEmitter extends MXMLEmitter
implements
emitClassDeclStart(cname, node.getBaseClassName(), false);
+ emitUIComponentDescriptorForDocument(node);
+
emitComplexInitializers(node);
emitPropertyDecls();
@@ -5132,8 +5136,6 @@ public class MXMLRoyaleEmitter extends MXMLEmitter
implements
write(pnode.getName());
write(ASEmitterTokens.DOUBLE_QUOTE);
writeToken(ASEmitterTokens.COMMA);
- write(ASEmitterTokens.THIS);
- write(ASEmitterTokens.MEMBER_ACCESS);
emitValueOrFactoryMethodCall(valueNode);
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.SEMICOLON);
@@ -5286,4 +5288,277 @@ public class MXMLRoyaleEmitter extends MXMLEmitter
implements
write(ASEmitterTokens.BLOCK_CLOSE);
writeNewline(ASEmitterTokens.SEMICOLON);
}
+
+ private void emitUIComponentDescriptorForDocument(IMXMLDocumentNode node)
+ {
+ if (!node.needsDocumentDescriptor())
+ {
+ return;
+ }
+
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSRoyaleEmitter.formatNamespacedProperty(
+ IMXMLTypeConstants.NAMESPACE_MX_INTERNAL.getName(),
+ "setDocumentDescriptor",
+ false));
+ write(ASEmitterTokens.PAREN_OPEN);
+ emitUIComponentDescriptor(node);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+
+ private void emitUIComponentDescriptor(IMXMLClassReferenceNode node)
+ {
+ if (!node.needsDescriptor())
+ {
+ return;
+ }
+ RoyaleJSProject fjp = (RoyaleJSProject) getMXMLWalker().getProject();
+ writeToken(ASEmitterTokens.NEW);
+ write(formatQualifiedName(fjp.getUIComponentDescriptorClass()));
+ write(ASEmitterTokens.PAREN_OPEN); // start of constructor args
+
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+ // type: mx.containers.HBox
+ write("type");
+ writeToken(ASEmitterTokens.COLON);
+
write(formatQualifiedName(node.getClassReference(fjp).getQualifiedName()));
+
+ // id: "hb1"
+ String id = node instanceof IMXMLInstanceNode ?
+ ((IMXMLInstanceNode)node).getEffectiveID() :
+ null;
+ if (id != null)
+ {
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+ write("id");
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ write(id);
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ }
+
+ emitUIComponentDescriptorProperties(node);
+ emitUIComponentDescriptorStyles(node);
+ emitUIComponentDescriptorEvents(node);
+
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ write(ASEmitterTokens.PAREN_CLOSE); // end of constructor args
+ }
+
+ private void emitUIComponentDescriptorProperties(IMXMLClassReferenceNode
node)
+ {
+ if (!node.isContainer() && !(node instanceof IMXMLInstanceNode))
+ {
+ return;
+ }
+
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+
+ write("propertiesFactory");
+ writeToken(ASEmitterTokens.COLON);
+
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+ writeToken(ASEmitterTokens.RETURN);
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+ int childDescriptorCount = 0;
+ if (node.isContainer())
+ {
+ write("childDescriptors");
+ writeToken(ASEmitterTokens.COLON);
+ indentPush();
+ writeNewline(ASEmitterTokens.SQUARE_OPEN);
+
+ // instance nodes not added to declarations will be children
+ for (int i = 0; i < node.getChildCount(); i++)
+ {
+ IASNode childNode = node.getChild(i);
+ if (childNode instanceof IMXMLInstanceNode)
+ {
+ IMXMLInstanceNode instanceNode = (IMXMLInstanceNode)
childNode;
+ if (childDescriptorCount > 0)
+ {
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+ }
+ childDescriptorCount++;
+ emitUIComponentDescriptor(instanceNode);
+ }
+ }
+
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ }
+
+ if (node instanceof IMXMLInstanceNode)
+ {
+ int actualPropCount = 0;
+ IMXMLPropertySpecifierNode[] propSpecifierNodes =
node.getPropertySpecifierNodes();
+ if (propSpecifierNodes != null)
+ {
+ for (IMXMLPropertySpecifierNode propNode : propSpecifierNodes)
+ {
+ if (propNode instanceof IMXMLStyleSpecifierNode)
+ {
+ continue;
+ }
+ if (childDescriptorCount > 0 || actualPropCount > 0)
+ {
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+ }
+ actualPropCount++;
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ write(propNode.getName());
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ writeToken(ASEmitterTokens.COLON);
+ emitValueOrFactoryMethodCall(propNode.getInstanceNode());
+ }
+ }
+ }
+
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+
+ indentPop();
+ writeNewline(ASEmitterTokens.SEMICOLON);
+
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ private void emitUIComponentDescriptorStyles(IMXMLClassReferenceNode node)
+ {
+ if (!(node instanceof IMXMLInstanceNode))
+ {
+ return;
+ }
+
+ IMXMLPropertySpecifierNode[] propSpecifierNodes =
node.getPropertySpecifierNodes();
+ if (propSpecifierNodes == null)
+ {
+ return;
+ }
+ IMXMLStyleSpecifierNode[] styleSpecifierNodes =
Arrays.stream(propSpecifierNodes)
+ .filter(propNode -> propNode instanceof
IMXMLStyleSpecifierNode)
+ .toArray(IMXMLStyleSpecifierNode[]::new);
+ if (styleSpecifierNodes.length == 0)
+ {
+ return;
+ }
+
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+
+ write("stylesFactory");
+ writeToken(ASEmitterTokens.COLON);
+
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+ for (int i = 0; i < styleSpecifierNodes.length; i++)
+ {
+ IMXMLStyleSpecifierNode styleNode = styleSpecifierNodes[i];
+ if (i > 0)
+ {
+ writeNewline();
+ }
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(styleNode.getName());
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ emitValueOrFactoryMethodCall(styleNode.getInstanceNode());
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ private void emitUIComponentDescriptorEvents(IMXMLClassReferenceNode node)
+ {
+ if (!(node instanceof IMXMLInstanceNode))
+ {
+ return;
+ }
+
+ IMXMLEventSpecifierNode[] eventSpecifierNodes =
node.getEventSpecifierNodes();
+ if (eventSpecifierNodes == null || eventSpecifierNodes.length == 0)
+ {
+ return;
+ }
+
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+
+ write("events");
+ writeToken(ASEmitterTokens.COLON);
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+ for (int i = 0; i < eventSpecifierNodes.length; i++)
+ {
+ IMXMLEventSpecifierNode eventNode = eventSpecifierNodes[i];
+ String listenerName = factoryMethodEventNames.get(eventNode);
+ if (i > 0)
+ {
+ write(ASEmitterTokens.COMMA);
+ writeNewline();
+ }
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ write(eventNode.getName());
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ // this is kind of funky, but it takes advantage of the fact that
+ // the value of an expression using the comma operator is based on
+ // the right side of the comma.
+ // we need to call Language.closure() somewhere to be sure that the
+ // listener is called with the correct "this" value, and it makes
+ // sense to keep it where events are defined.
+ IJSEmitter jsEmitter = (IJSEmitter) walker.getASEmitter();
+ jsEmitter.emitClosureStart();
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(listenerName);
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.THIS);
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(listenerName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ write(listenerName);
+ write(ASEmitterTokens.DOUBLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
}