8020223: ClassCastException: String can not be casted to ScriptFunction
authorsundar
Fri, 12 Jul 2013 15:27:16 +0530
changeset 18871 a27c6a5b999c
parent 18870 aa4fceda2fba
child 18872 bfb736c5aa43
8020223: ClassCastException: String can not be casted to ScriptFunction Reviewed-by: attila, lagergren
nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
nashorn/test/script/basic/JDK-8020223.js
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Jul 12 15:01:33 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Jul 12 15:27:16 2013 +0530
@@ -622,12 +622,15 @@
         case "getMethod":
             final FindProperty find = adaptee.findProperty(__call__, true);
             if (find != null) {
-                final ScriptFunctionImpl func = (ScriptFunctionImpl)getObjectValue(find);
-                // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
-                // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
-                return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
-                        func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
-                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
+                final Object value = getObjectValue(find);
+                if (value instanceof ScriptFunction) {
+                    final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
+                    // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
+                    // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
+                    return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
+                            func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
+                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
+                }
             }
             throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
         default:
@@ -687,16 +690,19 @@
         final MethodType type = desc.getMethodType();
         if (findData != null) {
             final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null;
-            final ScriptFunction func = (ScriptFunction)getObjectValue(findData);
+            final Object value = getObjectValue(findData);
+            if (value instanceof ScriptFunction) {
+                final ScriptFunction func = (ScriptFunction)value;
 
-            final MethodHandle methodHandle = getCallMethodHandle(findData, type,
+                final MethodHandle methodHandle = getCallMethodHandle(findData, type,
                     useName ? name : null);
-            if (methodHandle != null) {
-                return new GuardedInvocation(
-                        methodHandle,
-                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
-                        testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
-            }
+                if (methodHandle != null) {
+                    return new GuardedInvocation(
+                            methodHandle,
+                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
+                            testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
+                }
+             }
         }
 
         switch (hook) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Jul 12 15:01:33 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Jul 12 15:27:16 2013 +0530
@@ -1978,7 +1978,12 @@
             return noSuchProperty(desc, request);
         }
 
-        final ScriptFunction func = (ScriptFunction)getObjectValue(find);
+        final Object value = getObjectValue(find);
+        if (! (value instanceof ScriptFunction)) {
+            return createEmptyGetter(desc, name);
+        }
+
+        final ScriptFunction func = (ScriptFunction)value;
         final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
         // TODO: It'd be awesome if we could bind "name" without binding "this".
         return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class,
@@ -1998,8 +2003,13 @@
         final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
 
         if (find != null) {
-            final ScriptFunction func = (ScriptFunction)getObjectValue(find);
-            MethodHandle methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+            final Object value = getObjectValue(find);
+            ScriptFunction func = null;
+            MethodHandle methodHandle = null;
+            if (value instanceof ScriptFunction) {
+                func = (ScriptFunction)value;
+                methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+            }
 
             if (methodHandle != null) {
                 if (scopeAccess && func.isStrict()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8020223.js	Fri Jul 12 15:27:16 2013 +0530
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 2013, 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-8020223: ClassCastException: String can not be casted to ScriptFunction
+ *
+ * @test
+ * @run
+ */
+
+__noSuchMethod__ = "";
+
+try {
+    foo();
+    fail("Must have thrown exception");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        fail("TypeError expected, got " + e);
+    }
+}
+
+__noSuchProperty__ = 23;
+
+try {
+    foo;
+    fail("Must have thrown exception");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected, got " + e);
+    }
+}
+
+var obj = new JSAdapter() {
+    __get__: 332,
+    __call__: "hello"
+}
+
+try {
+    obj.foo; // should just be undefined
+} catch (e) {
+    fail("unexpected error : " + e);
+}
+
+try {
+    obj.foo();
+    fail("Must have thrown exception");
+} catch(e) {
+    if (! (e instanceof TypeError)) {
+        fail("TypeError expected, got " + e);
+    }
+}