diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeJavaMethod.java b/rhino/src/main/java/org/mozilla/javascript/NativeJavaMethod.java index 22df95d339..10c0456ce3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeJavaMethod.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeJavaMethod.java @@ -464,6 +464,9 @@ private static int preferSignature( break; } } + if (totalPreference == PREFERENCE_EQUAL && member1.isVarArgs() != member2.isVarArgs()) { + return member1.isVarArgs() ? PREFERENCE_SECOND_ARG : PREFERENCE_FIRST_ARG; + } return totalPreference; } diff --git a/tests/src/test/java/org/mozilla/javascript/tests/NativeJavaMethodTest.java b/tests/src/test/java/org/mozilla/javascript/tests/NativeJavaMethodTest.java index cb0e44c833..a037e27458 100644 --- a/tests/src/test/java/org/mozilla/javascript/tests/NativeJavaMethodTest.java +++ b/tests/src/test/java/org/mozilla/javascript/tests/NativeJavaMethodTest.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Supplier; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mozilla.javascript.Context; @@ -16,8 +17,11 @@ */ public class NativeJavaMethodTest { - public static class MethodDummy { + public abstract static class CaptureDummy { public final List captured = new ArrayList<>(); + } + + public static class MethodDummy extends CaptureDummy { public void f1(String s) { captured.add("1"); @@ -44,21 +48,50 @@ public void fN(String s1, String s2, String... sN) { } } - private static void expect(List expected, String... lines) { + public abstract static class NonVarArgParent extends CaptureDummy { + public void someMethod(int i) { + captured.add("NonVarArgParent.someMethod"); + } + } + + public static class VarArgAtSubclass extends NonVarArgParent { + public void someMethod(int i, int... extra) { + captured.add("VarArgAtSubclass.someMethod"); + } + } + + public abstract static class VarArgParent extends CaptureDummy { + public void someMethod(int i, int... extra) { + captured.add("VarArgParent.someMethod"); + } + } + + public static class VarArgAtParent extends VarArgParent { + public void someMethod(int i) { + captured.add("VarArgAtParent.someMethod"); + } + } + + public static void expect(List expected, String... lines) { + expect(expected, MethodDummy::new, lines); + } + + public static void expect( + List expected, Supplier beanSupplier, String... lines) { Utils.runWithAllModes( cx -> { - final var methodDummy = new MethodDummy(); - final var scope = initContext(cx, methodDummy); + final var bean = beanSupplier.get(); + final var scope = initContext(cx, bean); cx.evaluateString( scope, String.join("\n", lines), "NativeJavaMethodTest.js", 0, null); - Assertions.assertEquals(expected, methodDummy.captured); + Assertions.assertEquals(expected, bean.captured); return null; }); } - private static ScopeObject initContext(Context cx, MethodDummy methodDummy) { + private static ScopeObject initContext(Context cx, CaptureDummy methodDummy) { cx.setLanguageVersion(Context.VERSION_ES6); final var scope = cx.initStandardObjects(); ScriptableObject.putProperty(scope, "d", Context.javaToJS(methodDummy, scope)); @@ -107,6 +140,21 @@ void overload() { "d.f1('x', '3');"); } + @Test + void overloadMethodOrdering() { + expect( + List.of("NonVarArgParent.someMethod", "VarArgAtSubclass.someMethod"), + VarArgAtSubclass::new, + "d.someMethod(1);", + "d.someMethod(1, 2);"); + + expect( + List.of("VarArgAtParent.someMethod", "VarArgParent.someMethod"), + VarArgAtParent::new, + "d.someMethod(1);", + "d.someMethod(1, 2);"); + } + @Test void varArg() { expect(