diff --git a/src/main/java/com/alibaba/qlexpress4/Express4Runner.java b/src/main/java/com/alibaba/qlexpress4/Express4Runner.java index e42016ba1..9a7303f1d 100644 --- a/src/main/java/com/alibaba/qlexpress4/Express4Runner.java +++ b/src/main/java/com/alibaba/qlexpress4/Express4Runner.java @@ -642,7 +642,7 @@ public QCompileCache parseToDefinitionWithCache(String script) { return getParseFuture(script).get(); } catch (Exception e) { - Throwable compileException = e.getCause(); + Throwable compileException = e.getCause() != null ? e.getCause() : e; throw compileException instanceof QLSyntaxException ? (QLSyntaxException)compileException : new RuntimeException(compileException); } diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java b/src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java index d32012bd4..74241e364 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java @@ -352,8 +352,9 @@ private BiFunction> getFieldUnAccessible public static QLRuntimeException unwrapMethodInvokeEx(ErrorReporter errorReporter, String methodName, Exception ex) { if (ex instanceof IllegalArgumentException) { - return errorReporter.reportFormat(QLErrorCodes.INVOKE_METHOD_WITH_WRONG_ARGUMENTS.name(), - String.format(QLErrorCodes.INVOKE_METHOD_WITH_WRONG_ARGUMENTS.getErrorMsg(), methodName)); + return errorReporter.reportFormatWithCatch(ex, + QLErrorCodes.INVOKE_METHOD_WITH_WRONG_ARGUMENTS.name(), + QLErrorCodes.INVOKE_METHOD_WITH_WRONG_ARGUMENTS.getErrorMsg(), methodName); } else if (ex instanceof InvocationTargetException) { return errorReporter.report(((InvocationTargetException)ex).getTargetException(), diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/ForEachInstruction.java b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/ForEachInstruction.java index 67a8d3b55..9aef8edda 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/ForEachInstruction.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/ForEachInstruction.java @@ -59,7 +59,8 @@ else if (!(mayBeIterable instanceof Iterable)) { } } catch (UserDefineException e) { - throw errorReporter.reportFormat(QLErrorCodes.FOR_EACH_TYPE_MISMATCH.name(), + throw errorReporter.reportFormatWithCatch(e, + QLErrorCodes.FOR_EACH_TYPE_MISMATCH.name(), QLErrorCodes.FOR_EACH_TYPE_MISMATCH.getErrorMsg(), itCls.getName(), item == null ? "null" : item.getClass().getName()); @@ -69,7 +70,7 @@ else if (!(mayBeIterable instanceof Iterable)) { throw (QLRuntimeException)t; } // should not run there - throw errorReporter.report(QLErrorCodes.FOR_EACH_UNKNOWN_ERROR.name(), + throw errorReporter.report(t, QLErrorCodes.FOR_EACH_UNKNOWN_ERROR.name(), QLErrorCodes.FOR_EACH_UNKNOWN_ERROR.getErrorMsg()); } } diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewFilledInstanceInstruction.java b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewFilledInstanceInstruction.java index bf9f112a0..162778211 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewFilledInstanceInstruction.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewFilledInstanceInstruction.java @@ -69,7 +69,8 @@ private Object newInstance(QContext qContext) { QLErrorCodes.INVOKE_CONSTRUCTOR_INNER_ERROR.getErrorMsg()); } catch (Exception e) { - throw errorReporter.report(QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.name(), + throw errorReporter.report(e, + QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.name(), QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.getErrorMsg()); } } diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstruction.java b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstruction.java index 0efec4833..e8de92d65 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstruction.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstruction.java @@ -68,7 +68,8 @@ private Object newObject(Constructor constructor, Object[] params) { QLErrorCodes.INVOKE_CONSTRUCTOR_INNER_ERROR.getErrorMsg()); } catch (Exception e) { - throw errorReporter.report(QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.name(), + throw errorReporter.report(e, + QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.name(), QLErrorCodes.INVOKE_CONSTRUCTOR_UNKNOWN_ERROR.getErrorMsg()); } } diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/util/ThrowUtils.java b/src/main/java/com/alibaba/qlexpress4/runtime/util/ThrowUtils.java index b44f1935d..e5ab1fd24 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/util/ThrowUtils.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/util/ThrowUtils.java @@ -20,10 +20,10 @@ public static QLRuntimeException wrapThrowable(Throwable t, ErrorReporter errorR public static QLRuntimeException reportUserDefinedException(ErrorReporter errorReporter, UserDefineException e) { if (Objects.equals(e.getType(), UserDefineException.ExceptionType.INVALID_ARGUMENT)) { - throw errorReporter.report(QLErrorCodes.INVALID_ARGUMENT.name(), e.getMessage()); + throw errorReporter.report(e, QLErrorCodes.INVALID_ARGUMENT.name(), e.getMessage()); } else { - throw errorReporter.report(QLErrorCodes.BIZ_EXCEPTION.name(), e.getMessage()); + throw errorReporter.report(e, QLErrorCodes.BIZ_EXCEPTION.name(), e.getMessage()); } } } diff --git a/src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java b/src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java index 02739648f..788a987c9 100644 --- a/src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java +++ b/src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java @@ -1852,4 +1852,36 @@ public void defaultAndSwitchAsVariable() { .execute("default = 1\nswitch = 2;\ndefault+switch", Collections.emptyMap(), QLOptions.DEFAULT_OPTIONS); assertEquals(3, result.getResult()); } + + @Test + public void parseToDefinitionWithCacheInvalidScriptTest() { + Express4Runner express4Runner = new Express4Runner(InitOptions.DEFAULT_OPTIONS); + try { + express4Runner.parseToDefinitionWithCache("invalid syntax @@#$"); + fail("Expected QLSyntaxException for invalid script"); + } + catch (QLSyntaxException e) { + // The exception should have meaningful error information + assertNotNull(e.getMessage()); + } + } + + @Test + public void methodInvokeWrongArgTypeCausePreservedTest() { + Express4Runner express4Runner = + new Express4Runner(InitOptions.builder().securityStrategy(QLSecurityStrategy.open()).build()); + Map context = new HashMap<>(); + context.put("str", "hello"); + try { + // Call String.charAt with wrong argument type (passing a string instead of int) + express4Runner.execute("str.charAt(\"notAnInt\")", context, QLOptions.DEFAULT_OPTIONS); + fail("Expected QLRuntimeException for wrong argument type"); + } + catch (QLRuntimeException e) { + Assert.assertEquals("INVOKE_METHOD_WITH_WRONG_ARGUMENTS", e.getErrorCode()); + assertNotNull("Original IllegalArgumentException should be preserved as cause", e.getCause()); + assertTrue("Cause should be IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); + } + } } diff --git a/src/test/java/com/alibaba/qlexpress4/exception/MockErrorReporter.java b/src/test/java/com/alibaba/qlexpress4/exception/MockErrorReporter.java index b48298bd8..afd719f89 100644 --- a/src/test/java/com/alibaba/qlexpress4/exception/MockErrorReporter.java +++ b/src/test/java/com/alibaba/qlexpress4/exception/MockErrorReporter.java @@ -3,6 +3,6 @@ public class MockErrorReporter implements ErrorReporter { @Override public QLRuntimeException reportFormatWithCatch(Object catchObj, String errorCode, String format, Object... args) { - return new QLRuntimeException(null, String.format(format, args), errorCode); + return new QLRuntimeException(catchObj, String.format(format, args), errorCode); } } diff --git a/src/test/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstructionTest.java b/src/test/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstructionTest.java index d2c4b0164..e50a94be7 100644 --- a/src/test/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstructionTest.java +++ b/src/test/java/com/alibaba/qlexpress4/runtime/instruction/NewInstanceInstructionTest.java @@ -148,4 +148,19 @@ public void varArgTest() { mockQContextParent.pushParameter(parentParameters); newInstruction.execute(mockQContextParent, QLOptions.DEFAULT_OPTIONS); } + + @Test + public void exceptionCausePreservedTest() { + ErrorReporter errorReporter = new MockErrorReporter(); + NewInstanceInstruction newInstruction = new NewInstanceInstruction(errorReporter, SomeInter.class, 0); + MockQContextParent mockQContextParent = new MockQContextParent(false); + try { + newInstruction.execute(mockQContextParent, QLOptions.DEFAULT_OPTIONS); + Assert.fail("Expected QLRuntimeException"); + } + catch (QLRuntimeException e) { + Assert.assertEquals("INVOKE_CONSTRUCTOR_UNKNOWN_ERROR", e.getErrorCode()); + Assert.assertNotNull("Original exception should be preserved as cause", e.getCause()); + } + } }