You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2025/09/24 14:19:09 UTC

(commons-jexl) branch master updated: JEXL-447 : jxlt parsing fix, added test;

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

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f1371be JEXL-447 : jxlt parsing fix, added test;
7f1371be is described below

commit 7f1371be2b87df40501193115f557548d4357a62
Author: Henrib <hb...@gmail.com>
AuthorDate: Wed Sep 24 16:19:01 2025 +0200

    JEXL-447 : jxlt parsing fix, added test;
---
 RELEASE-NOTES.txt                                  |  3 +-
 src/changes/changes.xml                            |  6 +++
 .../org/apache/commons/jexl3/parser/Parser.jjt     |  2 +-
 .../org/apache/commons/jexl3/Issues400Test.java    | 22 +++++++++++
 src/test/scripts/test447.jexl                      | 44 ++++++++++++++++++++++
 5 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 001d4a37..e63a016e 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -50,11 +50,12 @@ New Features in 3.6.0:
 
 Bugs Fixed in 3.6.0:
 ====================
+* JEXL-447:     Regression in script-defined functions
+* JEXL-446:     ClassTool module inspection is too strict
 * JEXL-442:     Local variables are not resolved in interpolation string expression
 * JEXL-441:     Tokenization error if "\n" in template expression.
 * JEXL-439:     When using reference capture, incorrect scoping when local variable redefines a captured symbo
 * JEXL-437:     Semicolons actually not optional between function calls on separate lines
-* JEXL-446:     ClassTool module inspection is too strict
 
 
 ========================================================================================================================
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b85ce0c6..b1344889 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,12 @@
         <release version="3.6.0" date="YYYY-MM-DD"
                  description="This is a feature and maintenance release. Java 8 or later is required.">
             <!-- FIX -->
+            <action dev="henrib" type="fix" issue="JEXL-447" due-to="William Price">
+                Regression in script-defined functions
+            </action>
+            <action dev="William Price" type="fix" issue="JEXL-446" due-to="William Price">
+                ClassTool module inspection is too strict
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-442" due-to="Xu Pengcheng">
                 Local variables are not resolved in interpolation string expression.
             </action>
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index 1e11a37b..282e449c 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -358,7 +358,7 @@ TOKEN_MGR_DECLS : {
 <*> TOKEN :
 {
   < JXLT_LITERAL:
-    "`"("\n" | "\r" | "\r\n")* ("\\" "`" | ~["\u2028"-"\u202E","\u2066"-"\u2069"])*"`"
+    "`" (~["`","\\","\u2028"-"\u202E","\u2066"-"\u2069"] | "\\" ~["\u0000"])* "`"
   > : DEFAULT
 }
 
diff --git a/src/test/java/org/apache/commons/jexl3/Issues400Test.java b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
index 3c5eb7ad..4bfef0b9 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues400Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
@@ -28,6 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.Closeable;
+import java.io.File;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.util.Arrays;
@@ -800,5 +801,26 @@ public class Issues400Test {
         Object result = script.execute(context);
         Assertions.assertEquals("hello world", result);
     }
+
+
+    @Test
+    void testIssue447() {
+        JexlEngine jexl = new JexlBuilder().create();
+        String src = "const c = `${a}\n?= ${b}`; function foo(const left, const right) { `${left}\n?== ${right}` } c+foo(a, b)";
+        JexlScript script = jexl.createScript(src, "a", "b");
+        Object result = script.execute(null, "a", "b");
+        Assertions.assertEquals("a\n?= ba\n?== b", result);
+
+        final String TEST447 =  "src/test/scripts/test447.jexl";
+        final File src447 = new File(TEST447);
+        JexlScript script447 = jexl.createScript(src447);
+        Object result447 = script447.execute(null);
+        Assertions.assertInstanceOf(List.class, result447);
+        @SuppressWarnings("unchecked")
+        final List<Boolean> list = (List<Boolean>) result447;
+        for (Boolean item : list) {
+            Assertions.assertTrue(item);
+        }
+    }
 }
 
diff --git a/src/test/scripts/test447.jexl b/src/test/scripts/test447.jexl
new file mode 100644
index 00000000..51d1be86
--- /dev/null
+++ b/src/test/scripts/test447.jexl
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+let results = [...]
+
+function expect(const left, const right, const equal) {
+  let correct = (left == right) === equal && !(left != right) === equal;
+  results.add(correct ?: `${left} ?= ${right}`);
+  return results;
+}
+
+function expectStrict(const left, const right, const equal) {
+  let correct = (left === right) === equal && !(left !== right) === equal;
+  results.add(correct ?: `${left} ?== ${right}`);
+  return results;
+}
+
+
+expect(1.0,  1,    true);
+expect(1.1,  1,    false);
+expect(1.1,  1.1d, true);
+expect(1.1,  1.1f, false);
+expect('a', 'a',   true);
+expect('a', 'b',   false);
+expect('1',  1,    true);
+
+expectStrict(1.0,  1.0,  true);
+expectStrict(1.0,  1.0d, true);
+expectStrict(1.0,  1.0f, false);
+expectStrict(1.0,  1,    false);
+expectStrict(1,   '1',   false);
\ No newline at end of file