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 0158f0099 UnaryOperatorEmitter, BinaryOperatorEmitter: followup to 
adding JSDynamicOverride metadata, adding a new setMethodReversed attribute to 
optionally reverse key and value parameters
0158f0099 is described below

commit 0158f0099d0dd1a0e85667da1b6ab016d8989a16
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed Aug 12 14:24:27 2026 -0700

    UnaryOperatorEmitter, BinaryOperatorEmitter: followup to adding 
JSDynamicOverride metadata, adding a new setMethodReversed attribute to 
optionally reverse key and value parameters
    
    May be set to true or false. If true,  the key and value parameters are 
reversed so that the value is first. By default, the key is first, followed by 
the value.
    
    Followup to commits 308d8867b923c0edff4bf814fa89a175123dcf37 and 
b939a18ed7d101a505eda9c1aba5ec7b746d63d2
---
 .../constants/IJSMetaAttributeConstants.java       |   1 +
 .../codegen/js/jx/BinaryOperatorEmitter.java       | 164 ++++++++++++---------
 .../codegen/js/jx/UnaryOperatorEmitter.java        | 116 ++++++++++-----
 .../js/royale/TestRoyaleJSDynamicOverrides.java    |  24 ++-
 4 files changed, 189 insertions(+), 116 deletions(-)

diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
index ecbb3a81f..87463fcad 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
@@ -27,6 +27,7 @@ public interface IJSMetaAttributeConstants
     static final String NAME_DYNAMIC_OVERRIDE_SET_METHOD = "setMethod";
     static final String NAME_DYNAMIC_OVERRIDE_DELETE_METHOD = "deleteMethod";
     static final String NAME_DYNAMIC_OVERRIDE_IN_METHOD = "inMethod";
+    static final String NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED = 
"setMethodReversed";
 
     // [JSForInOverride]
     static final String ATTRIBUTE_FOR_IN_OVERRIDE = "JSForInOverride";
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 0096ae5bf..4e93c37d6 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -716,8 +716,6 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
         }
         else
         {
-                       boolean dynamicAssignmentOverride = false;
-                       boolean dynamicInOverride = false;
                        if (isAssignment
                                        && (getProject() instanceof 
RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null && 
((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
                                        && node.getLeftOperandNode() instanceof 
MemberAccessExpressionNode
@@ -751,40 +749,34 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                        else if (isAssignment && node.getLeftOperandNode() 
instanceof IDynamicAccessNode)
                        {
                                IDynamicAccessNode dynamicAccessNode = 
(IDynamicAccessNode) node.getLeftOperandNode();
-                               String setMethod = 
getDynamicAccessSetOverride(dynamicAccessNode);
-                               if (setMethod != null)
+                               IExpressionNode dynamicLeftOperandNode = 
dynamicAccessNode.getLeftOperandNode();
+                               IMetaTag dynamicOverrideMeta = 
getDynamicAccessOverride(dynamicLeftOperandNode);
+                               if (dynamicOverrideMeta != null)
                                {
-                                       dynamicAssignmentOverride = true;
-                                       
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
-                                       write(ASEmitterTokens.MEMBER_ACCESS);
-                                       write(setMethod);
-                                       write(ASEmitterTokens.PAREN_OPEN);
-                                       
getWalker().walk(dynamicAccessNode.getRightOperandNode());
-                                       write(ASEmitterTokens.COMMA);
-                               }
-                               else
-                               {
-                                       // normal dynamic access
-                                       
getWalker().walk(node.getLeftOperandNode());
+                                       String setMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD);
+                                       if (setMethod != null)
+                                       {
+                                               
emitAssignmentWithDynamicAccessOverride(node, dynamicAccessNode, setMethod, 
dynamicOverrideMeta);
+                                               return;
+                                       }
                                }
+                               // normal dynamic access
+                               getWalker().walk(node.getLeftOperandNode());
                        }
                        else if (id == ASTNodeID.Op_InID)
                        {
-                               String inMethod = 
getDynamicAccessInOverride(node.getRightOperandNode());
-                               if (inMethod != null)
+                               IMetaTag dynamicOverrideMeta = 
getDynamicAccessOverride(node.getRightOperandNode());
+                               if (dynamicOverrideMeta != null)
                                {
-                                       dynamicInOverride = true;
-                                       
getWalker().walk(node.getRightOperandNode());
-                                       write(ASEmitterTokens.MEMBER_ACCESS);
-                                       write(inMethod);
-                                       write(ASEmitterTokens.PAREN_OPEN);
-                                       
getWalker().walk(node.getLeftOperandNode());
-                               }
-                               else
-                               {
-                                       // normal in operator
-                                       
getWalker().walk(node.getLeftOperandNode());
+                                       String inMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_IN_METHOD);
+                                       if (inMethod != null)
+                                       {
+                                               
emitInWithDynamicAccessOverride(node, inMethod);
+                                               return;
+                                       }
                                }
+                               // normal in operator
+                               getWalker().walk(node.getLeftOperandNode());
                        }
             else getWalker().walk(node.getLeftOperandNode());
             startMapping(node, node.getLeftOperandNode());
@@ -793,7 +785,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                                //we need to use 'plus' method instead of '+'
                                xmlAdd = true;
                        }
-            if (id != ASTNodeID.Op_CommaID && !xmlAdd && 
!dynamicAssignmentOverride && !dynamicInOverride)
+            if (id != ASTNodeID.Op_CommaID && !xmlAdd)
                 write(ASEmitterTokens.SPACE);
 
             // (erikdebruin) rewrite 'a &&= b' to 'a = a && b'
@@ -814,7 +806,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                         : ASEmitterTokens.LOGICAL_OR);
                write(ASEmitterTokens.SPACE);
             }
-            else if (!dynamicAssignmentOverride && !dynamicInOverride)
+            else
             {
                                if (xmlAdd) {
                                        write(".plus(");
@@ -830,7 +822,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                        {
                                
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(), 
node.getLeftOperandNode().resolveType(getProject()));
                        }
-                       else if (!dynamicInOverride)
+                       else
                        {
                                getWalker().walk(node.getRightOperandNode());
                                
@@ -846,7 +838,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                                        write(".propertyNames()");
                                }
                        }
-                       if (xmlAdd || dynamicAssignmentOverride || 
dynamicInOverride) {
+                       if (xmlAdd) {
                                write(")");
                        }
         }
@@ -855,57 +847,23 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
             write(ASEmitterTokens.PAREN_CLOSE);
     }
 
-       private String getDynamicAccessSetOverride(IASNode leftSide)
+       private IMetaTag getDynamicAccessOverride(IExpressionNode context)
        {
-               if (!(leftSide instanceof DynamicAccessNode))
-               {
-                       return null;
-               }
-                       
-               IDynamicAccessNode dynamicAccessNode = (IDynamicAccessNode) 
leftSide;
-               IExpressionNode dynamicLeftOperandNode = 
dynamicAccessNode.getLeftOperandNode();
-               ITypeDefinition dynamicLeftType = 
dynamicLeftOperandNode.resolveType(getProject());
-               if (dynamicLeftType == null)
+               ITypeDefinition contextType = context.resolveType(getProject());
+               if (contextType == null)
                {
                        return null;
                }
                IMetaTag dynamicOverrideMeta = null;
-               for (ITypeDefinition currentType : 
dynamicLeftType.typeIteratable(getProject(), false))
+               for (ITypeDefinition currentType : 
contextType.typeIteratable(getProject(), false))
                {
                        dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
                        if (dynamicOverrideMeta != null)
                        {
-                               break;
+                               return dynamicOverrideMeta;
                        }
                }
-               if (dynamicOverrideMeta == null)
-               {
-                       return null;
-               }
-               return 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD);
-       }
-
-       private String getDynamicAccessInOverride(IExpressionNode rightSideOfIn)
-       {
-               ITypeDefinition typeDef = 
rightSideOfIn.resolveType(getProject());
-               if (typeDef == null)
-               {
-                       return null;
-               }
-               IMetaTag dynamicOverrideMeta = null;
-               for (ITypeDefinition currentType : 
typeDef.typeIteratable(getProject(), false))
-               {
-                       dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
-                       if (dynamicOverrideMeta != null)
-                       {
-                               break;
-                       }
-               }
-               if (dynamicOverrideMeta == null)
-               {
-                       return null;
-               }
-               return 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_IN_METHOD);
+               return null;
        }
     
     public static enum DatePropertiesGetters
@@ -1063,4 +1021,64 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
             write(ASEmitterTokens.PAREN_CLOSE);
                }
     }
+
+       private void 
emitAssignmentWithDynamicAccessOverride(IBinaryOperatorNode node, 
IDynamicAccessNode dynamicAccessNode, String setMethod, IMetaTag 
dynamicOverrideMeta)
+       {
+               boolean reversed = false;
+               String reversedValue = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED);
+               if (reversedValue != null)
+               {
+                       switch (reversedValue)
+                       {
+                               case "true":
+                                       reversed = true;
+                                       break;
+                // anything except true is treated as false
+                       }
+               }
+
+               getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+               startMapping(node);
+               write(ASEmitterTokens.MEMBER_ACCESS);
+               write(setMethod);
+               write(ASEmitterTokens.PAREN_OPEN);
+               endMapping(node);
+               if (!reversed)
+               {
+                       
getWalker().walk(dynamicAccessNode.getRightOperandNode());
+               }
+               else
+               {
+                       
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(), 
node.getLeftOperandNode().resolveType(getProject()));
+               }
+               startMapping(node);
+               write(ASEmitterTokens.COMMA);
+               write(ASEmitterTokens.SPACE);
+               endMapping(node);
+               if (!reversed)
+               {
+                       
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(), 
node.getLeftOperandNode().resolveType(getProject()));
+               }
+               else
+               {
+                       
getWalker().walk(dynamicAccessNode.getRightOperandNode());
+               }
+               startMapping(node);
+               write(ASEmitterTokens.PAREN_CLOSE);
+               endMapping(node);
+       }
+
+       private void emitInWithDynamicAccessOverride(IBinaryOperatorNode node, 
String inMethod)
+       {
+               getWalker().walk(node.getRightOperandNode());
+               startMapping(node);
+               write(ASEmitterTokens.MEMBER_ACCESS);
+               write(inMethod);
+               write(ASEmitterTokens.PAREN_OPEN);
+               endMapping(node);
+               getWalker().walk(node.getLeftOperandNode());
+               startMapping(node);
+               write(ASEmitterTokens.PAREN_CLOSE);
+               endMapping(node);
+       }
 }
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index 8de4c800c..5a374c4c7 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -113,46 +113,7 @@ public class UnaryOperatorEmitter extends JSSubEmitter 
implements
                     {
                         // BEFORE: abc[xyz]++
                         // AFTER:  abc.set(xyz, abc.get(xyz) + 1)
-
-                        
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
-                        startMapping(node);
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(setMethod);
-                        write(ASEmitterTokens.PAREN_OPEN);
-                        endMapping(node);
-                        
getWalker().walk(dynamicAccessNode.getRightOperandNode());
-                        writeToken(ASEmitterTokens.COMMA);
-
-                        
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
-                        startMapping(node);
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(getMethod);
-                        write(ASEmitterTokens.PAREN_OPEN);
-                        endMapping(node);
-                        
getWalker().walk(dynamicAccessNode.getRightOperandNode());
-                        startMapping(node);
-                        write(ASEmitterTokens.PAREN_CLOSE);
-                        endMapping(node);
-                        startMapping(node, dynamicAccessNode);
-                        if (node.getNodeID() == ASTNodeID.Op_PreIncrID
-                                || node.getNodeID() == ASTNodeID.Op_PostIncrID)
-                        {
-                            write(ASEmitterTokens.SPACE);
-                            write(OperatorType.PLUS.getOperatorText());
-                            write(ASEmitterTokens.SPACE);
-                            write("1");
-                        }
-                        else // decrement
-                        {
-                            write(ASEmitterTokens.SPACE);
-                            write(OperatorType.MINUS.getOperatorText());
-                            write(ASEmitterTokens.SPACE);
-                            write("1");
-                        }
-                        endMapping(node);
-                        startMapping(node);
-                        write(ASEmitterTokens.PAREN_CLOSE);
-                        endMapping(node);
+                        emitAssignmentWithDynamicAccessOverride(node, 
dynamicAccessNode, getMethod, setMethod, dynamicOverrideMeta);
                         return;
                     }
                 }
@@ -269,4 +230,79 @@ public class UnaryOperatorEmitter extends JSSubEmitter 
implements
         write(ASEmitterTokens.PAREN_CLOSE);
         endMapping(node);
     }
+
+    private void emitAssignmentWithDynamicAccessOverride(IUnaryOperatorNode 
node, IDynamicAccessNode dynamicAccessNode, String getMethod, String setMethod, 
IMetaTag dynamicOverrideMeta)
+    {
+        boolean reversed = false;
+        String reversedValue = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED);
+               if (reversedValue != null)
+               {
+                       switch (reversedValue)
+                       {
+                               case "true":
+                                       reversed = true;
+                                       break;
+                // anything except true is treated as false
+                       }
+        }
+
+        getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+        startMapping(node);
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(setMethod);
+        write(ASEmitterTokens.PAREN_OPEN);
+        endMapping(node);
+        if (!reversed)
+        {
+            getWalker().walk(dynamicAccessNode.getRightOperandNode());
+        }
+        else
+        {
+            emitDynamicAccessOverrideValue(node, dynamicAccessNode, getMethod, 
setMethod);
+        }
+        writeToken(ASEmitterTokens.COMMA);
+
+        if (!reversed)
+        {
+            emitDynamicAccessOverrideValue(node, dynamicAccessNode, getMethod, 
setMethod);
+        }
+        else
+        {
+            getWalker().walk(dynamicAccessNode.getRightOperandNode());
+        }
+    }
+
+    private void emitDynamicAccessOverrideValue(IUnaryOperatorNode node, 
IDynamicAccessNode dynamicAccessNode, String getMethod, String setMethod)
+    {
+        getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+        startMapping(node);
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(getMethod);
+        write(ASEmitterTokens.PAREN_OPEN);
+        endMapping(node);
+        getWalker().walk(dynamicAccessNode.getRightOperandNode());
+        startMapping(node);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        endMapping(node);
+        startMapping(node, dynamicAccessNode);
+        if (node.getNodeID() == ASTNodeID.Op_PreIncrID
+                || node.getNodeID() == ASTNodeID.Op_PostIncrID)
+        {
+            write(ASEmitterTokens.SPACE);
+            write(OperatorType.PLUS.getOperatorText());
+            write(ASEmitterTokens.SPACE);
+            write("1");
+        }
+        else // decrement
+        {
+            write(ASEmitterTokens.SPACE);
+            write(OperatorType.MINUS.getOperatorText());
+            write(ASEmitterTokens.SPACE);
+            write("1");
+        }
+        endMapping(node);
+        startMapping(node);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        endMapping(node);
+    }
 }
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
index 217296030..d41965656 100644
--- 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
@@ -71,7 +71,25 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(setMethod=\"set\")] class A { public function A() { 
this[0] = 123.4; } }",
                        IClassNode.class, WRAP_LEVEL_NONE);
         asBlockWalker.visitClass(node);
-        assertOut("/**\n * @constructor\n */\nA = function() {\n  
this.set(0,123.4);\n};");
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  this.set(0, 
123.4);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_setMethod_reversedTrue()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(setMethod=\"set\",setMethodReversed=\"true\")] 
class A { public function A() { this[0] = 123.4; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  
this.set(123.4, 0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_setMethod_reversedFalse()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(setMethod=\"set\",setMethodReversed=\"false\")] 
class A { public function A() { this[0] = 123.4; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  this.set(0, 
123.4);\n};");
     }
     
     @Test
@@ -80,7 +98,7 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { this[0] = 123.4; } }; 
[JSDynamicOverride(setMethod=\"set\")] public class A { public function A() {} 
}",
                        IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
-        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  this.set(0,123.4);\n};\ngoog.inherits(B, 
A);");
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  this.set(0, 123.4);\n};\ngoog.inherits(B, 
A);");
     }
     
     @Test
@@ -89,7 +107,7 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { this[0] = 123.4; } }; 
[JSDynamicOverride(setMethod=\"set\")] public interface A { }",
                        IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
-        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  this.set(0,123.4);\n};");
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  this.set(0, 123.4);\n};");
     }
     
     @Test

Reply via email to