You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by jo...@apache.org on 2026/08/13 17:20:18 UTC

(royale-compiler) branch develop updated: BinaryOperatorEmitter, UnaryOperatorEmitter, DynamicAccessEmitter: followup to ensure matching closing parentheses for JSDynamicAccessOverride

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 63cd0eaf2 BinaryOperatorEmitter, UnaryOperatorEmitter, DynamicAccessEmitter: followup to ensure matching closing parentheses for JSDynamicAccessOverride
63cd0eaf2 is described below

commit 63cd0eaf2d8b4fc5d909d0dc79c94bfc84181efb
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Aug 13 10:19:15 2026 -0700

    BinaryOperatorEmitter, UnaryOperatorEmitter, DynamicAccessEmitter: followup to ensure matching closing parentheses for JSDynamicAccessOverride
    
    Also added tests for parentheses to avoid future regressions.
    
    Followup to commit 308d8867b923c0edff4bf814fa89a175123dcf37
---
 .../codegen/js/jx/BinaryOperatorEmitter.java       |  4 ++
 .../codegen/js/jx/DynamicAccessEmitter.java        |  2 +
 .../codegen/js/jx/UnaryOperatorEmitter.java        |  2 +
 .../js/royale/TestRoyaleJSDynamicOverrides.java    | 72 ++++++++++++++++++++++
 4 files changed, 80 insertions(+)

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 4e93c37d6..24bb4ba56 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
@@ -757,6 +757,8 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
 					if (setMethod != null)
 					{
 						emitAssignmentWithDynamicAccessOverride(node, dynamicAccessNode, setMethod, dynamicOverrideMeta);
+						if (ASNodeUtils.hasParenClose(node))
+							write(ASEmitterTokens.PAREN_CLOSE);
 						return;
 					}
 				}
@@ -772,6 +774,8 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
 					if (inMethod != null)
 					{
 						emitInWithDynamicAccessOverride(node, inMethod);
+						if (ASNodeUtils.hasParenClose(node))
+							write(ASEmitterTokens.PAREN_CLOSE);
 						return;
 					}
 				}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index 7fbac28f1..bd2b44d56 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -109,6 +109,8 @@ public class DynamicAccessEmitter extends JSSubEmitter implements
 						write(ASEmitterTokens.PAREN_OPEN);
 						getWalker().walk(rightOperandNode);
 						write(ASEmitterTokens.PAREN_CLOSE);
+						if (ASNodeUtils.hasParenClose(node))
+							write(ASEmitterTokens.PAREN_CLOSE);
 						return;
 					}
 				}
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 5a374c4c7..32bc81793 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
@@ -114,6 +114,8 @@ public class UnaryOperatorEmitter extends JSSubEmitter implements
                         // BEFORE: abc[xyz]++
                         // AFTER:  abc.set(xyz, abc.get(xyz) + 1)
                         emitAssignmentWithDynamicAccessOverride(node, dynamicAccessNode, getMethod, setMethod, dynamicOverrideMeta);
+                        if (ASNodeUtils.hasParenClose(node))
+                            write(ASEmitterTokens.PAREN_CLOSE);
                         return;
                     }
                 }
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 d41965656..e9afb3ddb 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
@@ -47,6 +47,15 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         assertOut("/**\n * @constructor\n */\nA = function() {\n  var /** @type {*} */ a = this.get(0);\n};");
     }
     
+    @Test
+    public void testDynamicOverride_getMethod_parentheses()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(getMethod=\"get\")] class A { public function A() { var a = (this[0]); } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var /** @type {*} */ a = (this.get(0));\n};");
+    }
+    
     @Test
     public void testDynamicOverride_getMethod_subclass()
     {
@@ -74,6 +83,15 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         assertOut("/**\n * @constructor\n */\nA = function() {\n  this.set(0, 123.4);\n};");
     }
     
+    @Test
+    public void testDynamicOverride_setMethod_parentheses()
+    {
+        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};");
+    }
+    
     @Test
     public void testDynamicOverride_setMethod_reversedTrue()
     {
@@ -119,6 +137,15 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         assertOut("/**\n * @constructor\n */\nA = function() {\n  this.del(0);\n};");
     }
     
+    @Test
+    public void testDynamicOverride_deleteMethod_parentheses()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(deleteMethod=\"del\")] class A { public function A() { (delete this[0]); } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  (this.del(0));\n};");
+    }
+    
     @Test
     public void testDynamicOverride_deleteMethod_subclass()
     {
@@ -146,6 +173,15 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         assertOut("/**\n * @constructor\n */\nA = function() {\n  this.exists(0);\n};");
     }
     
+    @Test
+    public void testDynamicOverride_inMethod_parentheses()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(inMethod=\"exists\")] class A { public function A() { (0 in this); } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  (this.exists(0));\n};");
+    }
+    
     @Test
     public void testDynamicOverride_inMethod_subclass()
     {
@@ -163,6 +199,42 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = function() {\n  this.exists(0);\n};");
     }
+    
+    @Test
+    public void testDynamicOverride_getMethod_setMethod_postIncrement()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(getMethod=\"get\",setMethod=\"set\")] class A { public function A() { this[0]++; } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  this.set(0, this.get(0) + 1);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod_setMethod_postIncrement_parentheses()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(getMethod=\"get\",setMethod=\"set\")] class A { public function A() { (this[0]++); } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  (this.set(0, this.get(0) + 1));\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod_setMethod_postDecrement()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(getMethod=\"get\",setMethod=\"set\")] class A { public function A() { this[0]--; } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  this.set(0, this.get(0) - 1);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod_setMethod_postDecrement_parentheses()
+    {
+        IClassNode node = (IClassNode) getNode("[JSDynamicOverride(getMethod=\"get\",setMethod=\"set\")] class A { public function A() { (this[0]--); } }",
+        		IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  (this.set(0, this.get(0) - 1));\n};");
+    }
 
     @Override
     protected IBackend createBackend()