# HG changeset patch # User sundar # Date 1373623036 -19800 # Node ID 1a6b1799f5334e15ce1fe9ae480c7cb53c8c5881 # Parent d763da2472441aac732e0e14087abb7483966f6e 8020223: ClassCastException: String can not be casted to ScriptFunction Reviewed-by: attila, lagergren diff -r d763da247244 -r 1a6b1799f533 src/jdk/nashorn/internal/objects/NativeJSAdapter.java --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Fri Jul 12 15:01:33 2013 +0530 +++ b/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) { diff -r d763da247244 -r 1a6b1799f533 src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jul 12 15:01:33 2013 +0530 +++ b/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()) { diff -r d763da247244 -r 1a6b1799f533 test/script/basic/JDK-8020223.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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); + } +}