From 893a8f05eed24b95e232cb28a9c7f1b4a3ff3c40 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Wed, 28 Feb 2024 13:40:57 +0100 Subject: [PATCH] When InterfaceAdapter is used, the wrong thisObj is used --- .../mozilla/javascript/InterfaceAdapter.java | 3 +- .../tests/JavaAdapterInvokeTest.java | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 testsrc/org/mozilla/javascript/tests/JavaAdapterInvokeTest.java diff --git a/src/org/mozilla/javascript/InterfaceAdapter.java b/src/org/mozilla/javascript/InterfaceAdapter.java index 513101920b..e850522a42 100644 --- a/src/org/mozilla/javascript/InterfaceAdapter.java +++ b/src/org/mozilla/javascript/InterfaceAdapter.java @@ -152,9 +152,8 @@ Object invokeImpl( } } } - Scriptable thisObj = wf.wrapAsJavaObject(cx, topScope, thisObject, null); - Object result = function.call(cx, topScope, thisObj, args); + Object result = function.call(cx, topScope, (Scriptable) target, args); Class javaResultType = method.getReturnType(); if (javaResultType == Void.TYPE) { result = null; diff --git a/testsrc/org/mozilla/javascript/tests/JavaAdapterInvokeTest.java b/testsrc/org/mozilla/javascript/tests/JavaAdapterInvokeTest.java new file mode 100644 index 0000000000..6ef569f6ed --- /dev/null +++ b/testsrc/org/mozilla/javascript/tests/JavaAdapterInvokeTest.java @@ -0,0 +1,111 @@ +package org.mozilla.javascript.tests; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +public class JavaAdapterInvokeTest { + Context cx = null; + Scriptable topScope = null; + + @Before + public void enterContext() { + cx = Context.enter(); + cx.setOptimizationLevel(-1); + topScope = cx.initStandardObjects(); + } + + @After + public void exitContext() { + Context.exit(); + } + + public interface AdapterInterface { + int m1(int i); + + int m2(); + } + + public static class AdapterClass { + private AdapterInterface adapter; + + public AdapterClass(AdapterInterface adapter) { + this.adapter = adapter; + } + + public int doIt(int i) { + return this.adapter.m1(i) + this.adapter.m2(); + } + } + + @Test + public void testInvoke() throws NoSuchMethodException { + String testCode = + "'use strict'\n" + + "var impl = {" + + " m1: function(i) { return i + 1 },\n" + + " m2: function() { return 7 }\n" + + "}\n" + + "adapter = new Packages." + + AdapterClass.class.getName() + + "(impl)\n" + + "adapter.doIt(42)"; + + Number result = (Number) cx.evaluateString(topScope, testCode, "", 1, null); + Assert.assertEquals(50, result.intValue()); + } + + @Test + public void testInvokeWithPrototype() throws NoSuchMethodException { + String testCode = + "'use strict'\n" + + "function Obj() {}\n" + + "Obj.prototype.m1 = function(i) { return i + 1 }\n" + + "Obj.prototype.m2 = function() { return 7 }\n" + + "var impl = new Obj()\n" + + "adapter = new Packages." + + AdapterClass.class.getName() + + "(impl)\n" + + "adapter.doIt(42)"; + + Number result = (Number) cx.evaluateString(topScope, testCode, "", 1, null); + Assert.assertEquals(50, result.intValue()); + } + + @Test + public void testInvokeWithPrototypeAndCtor() throws NoSuchMethodException { + String testCode = + "'use strict'\n" + + "function Obj() { this.myObj = {one: 1} }\n" + + "Obj.prototype.m1 = function(i) { return i + this.myObj.one }\n" + + "Obj.prototype.m2 = function() { return 7 }\n" + + "var impl = new Obj()\n" + + "adapter = new Packages." + + AdapterClass.class.getName() + + "(impl)\n" + + "adapter.doIt(42)"; + + Number result = (Number) cx.evaluateString(topScope, testCode, "", 1, null); + Assert.assertEquals(50, result.intValue()); + } + + @Test + public void testInvokeJsOnly() throws NoSuchMethodException { + String testCode = + "'use strict'\n" + + "function Obj() { this.myObj = {one: 1} }\n" + + "Obj.prototype.m1 = function(i) { return i + this.myObj.one }\n" + + "Obj.prototype.m2 = function() { return 7 }\n" + + "function Adapter(adapter) { this.adapter = adapter }\n" + + "Adapter.prototype.doIt = function(i) { return this.adapter.m1(i) + this.adapter.m2() }\n" + + "var impl = new Obj()\n" + + "adapter = new Adapter(impl)\n" + + "adapter.doIt(42)"; + + Number result = (Number) cx.evaluateString(topScope, testCode, "", 1, null); + Assert.assertEquals(50, result.intValue()); + } +}