8067136: BrowserJSObjectLinker does not handle call on JSObjects
authorsundar
Wed, 10 Dec 2014 19:42:01 +0530
changeset 27973 ecc16e813691
parent 27972 8ec664fdf8da
child 27974 4eca5d2c0088
8067136: BrowserJSObjectLinker does not handle call on JSObjects Reviewed-by: attila, hannesw, lagergren
nashorn/samples/browser_dom.js
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
nashorn/test/script/basic/JDK-8067136.js
nashorn/test/script/basic/JDK-8067136.js.EXPECTED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/browser_dom.js	Wed Dec 10 19:42:01 2014 +0530
@@ -0,0 +1,91 @@
+#// Usage: jjs -fx browser.js
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!$OPTIONS._fx) {
+    print("Usage: jjs -fx browser.js");
+    exit(1);
+}
+
+// JavaFX classes used
+var ChangeListener = Java.type("javafx.beans.value.ChangeListener");
+var Scene     = Java.type("javafx.scene.Scene");
+var WebView   = Java.type("javafx.scene.web.WebView");
+var EventListener = Java.type("org.w3c.dom.events.EventListener");
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Web View";
+    var wv = new WebView();
+    wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+This is the title
+</title>
+<script>
+// click count for OK button
+var okCount = 0;
+</script>
+</head>
+<body>
+Button from the input html<br>
+<button type="button" onclick="okCount++">OK</button><br>
+</body>
+</html>
+EOF, "text/html");
+
+    // attach onload handler
+    wv.engine.loadWorker.stateProperty().addListener(
+        new ChangeListener() {
+            changed: function() {
+               // DOM document element
+               var document = wv.engine.document;
+               // DOM manipulation
+               var btn = document.createElement("button");
+               var n = 0;
+               // attach a button handler - nashorn function!
+               btn.onclick = new EventListener(function() {
+                   n++; print("You clicked " + n + " time(s)");
+                   print("you clicked OK " + wv.engine.executeScript("okCount"));
+               });
+               // attach text to button
+               var t = document.createTextNode("Click Me!"); 
+               btn.appendChild(t);
+               // attach button to the document
+               document.body.appendChild(btn); 
+           }
+        }
+    );
+    stage.scene = new Scene(wv, 750, 500);
+    stage.show();
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Wed Dec 10 12:30:48 2014 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Wed Dec 10 19:42:01 2014 +0530
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -131,6 +132,8 @@
             case "setProp":
             case "setElem":
                 return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
+            case "call":
+                return findCallMethod(desc);
             default:
                 return null;
         }
@@ -156,6 +159,11 @@
         return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
     }
 
+    private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
+        final MethodHandle call = MH.insertArguments(JSOBJECT_CALL, 1, "call");
+        return new GuardedInvocation(MH.asCollector(call, Object[].class, desc.getMethodType().parameterCount() - 1), IS_JSOBJECT_GUARD);
+    }
+
     @SuppressWarnings("unused")
     private static boolean isJSObject(final Object self) {
         return jsObjectClass.isInstance(self);
@@ -215,6 +223,7 @@
         static final MethodHandle JSOBJECT_GETSLOT       = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class));
         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));
         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));
+        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));
 
         private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
             checkJSObjectClass();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8067136.js	Wed Dec 10 19:42:01 2014 +0530
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8067136: BrowserJSObjectLinker does not handle call on JSObjects
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// call on netscape.javascript.JSObject
+
+function main() {
+    var JSObject;
+    try {
+        JSObject = Java.type("netscape.javascript.JSObject");
+    } catch (e) {
+        if (e instanceof java.lang.ClassNotFoundException) {
+            // pass vacuously by emitting the .EXPECTED file content
+            var str = readFully(__DIR__ + "JDK-8067136.js.EXPECTED");
+            print(str.substring(0, str.length - 1));
+            return;
+        } else{
+            fail("unexpected exception for JSObject", e);
+        }
+    }
+    test(JSObject);
+}
+
+function test(JSObject) {
+    var obj = new (Java.extend(JSObject))() {
+        getMember: function(name) {
+            if (name == "func") {
+                return new (Java.extend(JSObject)) {
+                    call: function(n) {
+                        print("func called");
+                    }
+                }
+            }
+            return name.toUpperCase();
+        },
+
+    };
+
+    obj.func();
+}
+
+main();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8067136.js.EXPECTED	Wed Dec 10 19:42:01 2014 +0530
@@ -0,0 +1,1 @@
+func called