8170565: JSObject call() is passed undefined for the argument 'thiz'
Reviewed-by: hannesw, jlaskey, attila
This commit is contained in:
parent
7fe5109735
commit
fa4bdd39c5
@ -40,9 +40,13 @@ import jdk.dynalink.linker.LinkRequest;
|
||||
import jdk.dynalink.linker.LinkerServices;
|
||||
import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.nashorn.api.scripting.JSObject;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.objects.Global;
|
||||
|
||||
/**
|
||||
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
|
||||
@ -142,9 +146,9 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker {
|
||||
}
|
||||
|
||||
private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
|
||||
MethodHandle mh = JSOBJECT_CALL;
|
||||
MethodHandle mh = NashornCallSiteDescriptor.isScope(desc)? JSOBJECT_SCOPE_CALL : JSOBJECT_CALL;
|
||||
if (NashornCallSiteDescriptor.isApplyToCall(desc)) {
|
||||
mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL);
|
||||
mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, mh);
|
||||
}
|
||||
final MethodType type = desc.getMethodType();
|
||||
mh = type.parameterType(type.parameterCount() - 1) == Object[].class ?
|
||||
@ -215,6 +219,19 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker {
|
||||
}
|
||||
}
|
||||
|
||||
// This is used when a JSObject is called as scope call to do undefined -> Global this translation.
|
||||
@SuppressWarnings("unused")
|
||||
private static Object jsObjectScopeCall(final JSObject jsObj, final Object thiz, final Object[] args) {
|
||||
final Object modifiedThiz;
|
||||
if (thiz == ScriptRuntime.UNDEFINED && !jsObj.isStrictFunction()) {
|
||||
final Global global = Context.getGlobal();
|
||||
modifiedThiz = ScriptObjectMirror.wrap(global, global);
|
||||
} else {
|
||||
modifiedThiz = thiz;
|
||||
}
|
||||
return jsObj.call(modifiedThiz, args);
|
||||
}
|
||||
|
||||
private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
|
||||
|
||||
// method handles of the current class
|
||||
@ -226,6 +243,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker {
|
||||
private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class);
|
||||
private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class);
|
||||
private static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle JSOBJECT_SCOPE_CALL = findOwnMH_S("jsObjectScopeCall", Object.class, JSObject.class, Object.class, Object[].class);
|
||||
private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class);
|
||||
private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class);
|
||||
|
||||
|
@ -41,6 +41,7 @@ import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import jdk.nashorn.api.scripting.AbstractJSObject;
|
||||
import jdk.nashorn.api.scripting.JSObject;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import org.testng.annotations.Test;
|
||||
@ -389,4 +390,41 @@ public class ScriptObjectMirrorTest {
|
||||
assertTrue(func.isFunction());
|
||||
assertEquals(func.call(e.eval("this"), "hello"), "hello world");
|
||||
}
|
||||
|
||||
// @bug 8170565: JSObject call() is passed undefined for the argument 'thiz'
|
||||
@Test
|
||||
public void jsObjectThisTest() throws Exception {
|
||||
final ScriptEngineManager engineManager = new ScriptEngineManager();
|
||||
final ScriptEngine e = engineManager.getEngineByName("nashorn");
|
||||
e.put("func", new AbstractJSObject() {
|
||||
@Override
|
||||
public boolean isFunction() { return true; }
|
||||
|
||||
@Override
|
||||
public Object call(Object thiz, Object...args) {
|
||||
return thiz;
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue((boolean)e.eval("func() === this"));
|
||||
|
||||
// check that there is no blind undefined->Global translation!
|
||||
assertTrue((boolean)e.eval("typeof(Function.prototype.call.call(func, undefined)) == 'undefined'"));
|
||||
|
||||
// make sure that strict functions don't get translated this for scope calls!
|
||||
e.put("sfunc", new AbstractJSObject() {
|
||||
@Override
|
||||
public boolean isFunction() { return true; }
|
||||
|
||||
@Override
|
||||
public boolean isStrictFunction() { return true; }
|
||||
|
||||
@Override
|
||||
public Object call(Object thiz, Object...args) {
|
||||
return thiz;
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue((boolean)e.eval("typeof sfunc() == 'undefined'"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user