OpenJDK / jdk / jdk10
changeset 42382:e56aaa43d9f4
8170565: JSObject call() is passed undefined for the argument 'thiz'
Reviewed-by: hannesw, jlaskey, attila
author | sundar |
---|---|
date | Thu, 01 Dec 2016 18:53:51 +0530 |
parents | a21d6681a19d |
children | 7c6ddb187262 |
files | nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java |
diffstat | 2 files changed, 58 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Dec 01 11:17:05 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Dec 01 18:53:51 2016 +0530 @@ -40,9 +40,13 @@ 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 @@ } 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 @@ } } + // 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 @@ 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);
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Thu Dec 01 11:17:05 2016 +0000 +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Thu Dec 01 18:53:51 2016 +0530 @@ -41,6 +41,7 @@ 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 @@ 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'")); + } }