Wed, 10 Dec 2014 19:42:01 +0530
8067136: BrowserJSObjectLinker does not handle call on JSObjects
Reviewed-by: attila, hannesw, lagergren
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/samples/browser_dom.js Wed Dec 10 19:42:01 2014 +0530 1.3 @@ -0,0 +1,91 @@ 1.4 +#// Usage: jjs -fx browser.js 1.5 + 1.6 +/* 1.7 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions 1.11 + * are met: 1.12 + * 1.13 + * - Redistributions of source code must retain the above copyright 1.14 + * notice, this list of conditions and the following disclaimer. 1.15 + * 1.16 + * - Redistributions in binary form must reproduce the above copyright 1.17 + * notice, this list of conditions and the following disclaimer in the 1.18 + * documentation and/or other materials provided with the distribution. 1.19 + * 1.20 + * - Neither the name of Oracle nor the names of its 1.21 + * contributors may be used to endorse or promote products derived 1.22 + * from this software without specific prior written permission. 1.23 + * 1.24 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 1.25 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 1.26 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1.27 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1.28 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.29 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.30 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.31 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1.32 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.33 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.34 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.35 + */ 1.36 + 1.37 +if (!$OPTIONS._fx) { 1.38 + print("Usage: jjs -fx browser.js"); 1.39 + exit(1); 1.40 +} 1.41 + 1.42 +// JavaFX classes used 1.43 +var ChangeListener = Java.type("javafx.beans.value.ChangeListener"); 1.44 +var Scene = Java.type("javafx.scene.Scene"); 1.45 +var WebView = Java.type("javafx.scene.web.WebView"); 1.46 +var EventListener = Java.type("org.w3c.dom.events.EventListener"); 1.47 + 1.48 +// JavaFX start method 1.49 +function start(stage) { 1.50 + start.title = "Web View"; 1.51 + var wv = new WebView(); 1.52 + wv.engine.loadContent(<<EOF 1.53 +<html> 1.54 +<head> 1.55 +<title> 1.56 +This is the title 1.57 +</title> 1.58 +<script> 1.59 +// click count for OK button 1.60 +var okCount = 0; 1.61 +</script> 1.62 +</head> 1.63 +<body> 1.64 +Button from the input html<br> 1.65 +<button type="button" onclick="okCount++">OK</button><br> 1.66 +</body> 1.67 +</html> 1.68 +EOF, "text/html"); 1.69 + 1.70 + // attach onload handler 1.71 + wv.engine.loadWorker.stateProperty().addListener( 1.72 + new ChangeListener() { 1.73 + changed: function() { 1.74 + // DOM document element 1.75 + var document = wv.engine.document; 1.76 + // DOM manipulation 1.77 + var btn = document.createElement("button"); 1.78 + var n = 0; 1.79 + // attach a button handler - nashorn function! 1.80 + btn.onclick = new EventListener(function() { 1.81 + n++; print("You clicked " + n + " time(s)"); 1.82 + print("you clicked OK " + wv.engine.executeScript("okCount")); 1.83 + }); 1.84 + // attach text to button 1.85 + var t = document.createTextNode("Click Me!"); 1.86 + btn.appendChild(t); 1.87 + // attach button to the document 1.88 + document.body.appendChild(btn); 1.89 + } 1.90 + } 1.91 + ); 1.92 + stage.scene = new Scene(wv, 750, 500); 1.93 + stage.show(); 1.94 +}
2.1 --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Tue Dec 09 13:15:27 2014 -0800 2.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Dec 10 19:42:01 2014 +0530 2.3 @@ -29,6 +29,7 @@ 2.4 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT; 2.5 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER; 2.6 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT; 2.7 +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL; 2.8 import java.lang.invoke.MethodHandle; 2.9 import java.lang.invoke.MethodHandles; 2.10 import jdk.internal.dynalink.CallSiteDescriptor; 2.11 @@ -123,6 +124,8 @@ 2.12 case "setProp": 2.13 case "setElem": 2.14 return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); 2.15 + case "call": 2.16 + return findCallMethod(desc); 2.17 default: 2.18 return null; 2.19 } 2.20 @@ -148,6 +151,11 @@ 2.21 return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD); 2.22 } 2.23 2.24 + private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) { 2.25 + final MethodHandle call = MH.insertArguments(JSOBJECT_CALL, 1, "call"); 2.26 + return new GuardedInvocation(MH.asCollector(call, Object[].class, desc.getMethodType().parameterCount() - 1), IS_JSOBJECT_GUARD); 2.27 + } 2.28 + 2.29 @SuppressWarnings("unused") 2.30 private static boolean isJSObject(final Object self) { 2.31 return jsObjectClass.isInstance(self); 2.32 @@ -207,6 +215,7 @@ 2.33 static final MethodHandle JSOBJECT_GETSLOT = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class)); 2.34 static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class).asType(MH.type(Void.TYPE, Object.class, String.class, Object.class)); 2.35 static final MethodHandle JSOBJECT_SETSLOT = findJSObjectMH_V("setSlot", Void.TYPE, int.class, Object.class).asType(MH.type(Void.TYPE, Object.class, int.class, Object.class)); 2.36 + static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, String.class, Object[].class).asType(MH.type(Object.class, Object.class, String.class, Object[].class)); 2.37 2.38 private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 2.39 checkJSObjectClass();
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8067136.js Wed Dec 10 19:42:01 2014 +0530 3.3 @@ -0,0 +1,69 @@ 3.4 +/* 3.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * JDK-8067136: BrowserJSObjectLinker does not handle call on JSObjects 3.29 + * 3.30 + * @test 3.31 + * @option -scripting 3.32 + * @run 3.33 + */ 3.34 + 3.35 +// call on netscape.javascript.JSObject 3.36 + 3.37 +function main() { 3.38 + var JSObject; 3.39 + try { 3.40 + JSObject = Java.type("netscape.javascript.JSObject"); 3.41 + } catch (e) { 3.42 + if (e instanceof java.lang.ClassNotFoundException) { 3.43 + // pass vacuously by emitting the .EXPECTED file content 3.44 + var str = readFully(__DIR__ + "JDK-8067136.js.EXPECTED"); 3.45 + print(str.substring(0, str.length - 1)); 3.46 + return; 3.47 + } else{ 3.48 + fail("unexpected exception for JSObject", e); 3.49 + } 3.50 + } 3.51 + test(JSObject); 3.52 +} 3.53 + 3.54 +function test(JSObject) { 3.55 + var obj = new (Java.extend(JSObject))() { 3.56 + getMember: function(name) { 3.57 + if (name == "func") { 3.58 + return new (Java.extend(JSObject)) { 3.59 + call: function(n) { 3.60 + print("func called"); 3.61 + } 3.62 + } 3.63 + } 3.64 + return name.toUpperCase(); 3.65 + }, 3.66 + 3.67 + }; 3.68 + 3.69 + obj.func(); 3.70 +} 3.71 + 3.72 +main();
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/script/basic/JDK-8067136.js.EXPECTED Wed Dec 10 19:42:01 2014 +0530 4.3 @@ -0,0 +1,1 @@ 4.4 +func called