Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When InterfaceAdapter is used, the wrong thisObj is used #1453

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/org/mozilla/javascript/InterfaceAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,8 @@ Object invokeImpl(
}
}
}
Scriptable thisObj = wf.wrapAsJavaObject(cx, topScope, thisObject, null);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thisObject is an instance of JavaAdapterInvokeTest.AdapterClass and we want to call a method on target


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;
Expand Down
111 changes: 111 additions & 0 deletions testsrc/org/mozilla/javascript/tests/JavaAdapterInvokeTest.java
Original file line number Diff line number Diff line change
@@ -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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno what our policy is, but should this test not also be run in non-interpreted mode?

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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a testcase where .myObj is added on the prototype, instead of the this inside the constructor?

+ "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());
}
}
Loading