Fri, 12 Jul 2013 15:27:16 +0530
8020223: ClassCastException: String can not be casted to ScriptFunction
Reviewed-by: attila, lagergren
1.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Fri Jul 12 15:01:33 2013 +0530 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Fri Jul 12 15:27:16 2013 +0530 1.3 @@ -622,12 +622,15 @@ 1.4 case "getMethod": 1.5 final FindProperty find = adaptee.findProperty(__call__, true); 1.6 if (find != null) { 1.7 - final ScriptFunctionImpl func = (ScriptFunctionImpl)getObjectValue(find); 1.8 - // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound 1.9 - // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. 1.10 - return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, 1.11 - func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), 1.12 - adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null)); 1.13 + final Object value = getObjectValue(find); 1.14 + if (value instanceof ScriptFunction) { 1.15 + final ScriptFunctionImpl func = (ScriptFunctionImpl)value; 1.16 + // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound 1.17 + // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. 1.18 + return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, 1.19 + func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), 1.20 + adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null)); 1.21 + } 1.22 } 1.23 throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this)); 1.24 default: 1.25 @@ -687,16 +690,19 @@ 1.26 final MethodType type = desc.getMethodType(); 1.27 if (findData != null) { 1.28 final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null; 1.29 - final ScriptFunction func = (ScriptFunction)getObjectValue(findData); 1.30 + final Object value = getObjectValue(findData); 1.31 + if (value instanceof ScriptFunction) { 1.32 + final ScriptFunction func = (ScriptFunction)value; 1.33 1.34 - final MethodHandle methodHandle = getCallMethodHandle(findData, type, 1.35 + final MethodHandle methodHandle = getCallMethodHandle(findData, type, 1.36 useName ? name : null); 1.37 - if (methodHandle != null) { 1.38 - return new GuardedInvocation( 1.39 - methodHandle, 1.40 - adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), 1.41 - testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func)); 1.42 - } 1.43 + if (methodHandle != null) { 1.44 + return new GuardedInvocation( 1.45 + methodHandle, 1.46 + adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), 1.47 + testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func)); 1.48 + } 1.49 + } 1.50 } 1.51 1.52 switch (hook) {
2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jul 12 15:01:33 2013 +0530 2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jul 12 15:27:16 2013 +0530 2.3 @@ -1978,7 +1978,12 @@ 2.4 return noSuchProperty(desc, request); 2.5 } 2.6 2.7 - final ScriptFunction func = (ScriptFunction)getObjectValue(find); 2.8 + final Object value = getObjectValue(find); 2.9 + if (! (value instanceof ScriptFunction)) { 2.10 + return createEmptyGetter(desc, name); 2.11 + } 2.12 + 2.13 + final ScriptFunction func = (ScriptFunction)value; 2.14 final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this; 2.15 // TODO: It'd be awesome if we could bind "name" without binding "this". 2.16 return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class, 2.17 @@ -1998,8 +2003,13 @@ 2.18 final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); 2.19 2.20 if (find != null) { 2.21 - final ScriptFunction func = (ScriptFunction)getObjectValue(find); 2.22 - MethodHandle methodHandle = getCallMethodHandle(func, desc.getMethodType(), name); 2.23 + final Object value = getObjectValue(find); 2.24 + ScriptFunction func = null; 2.25 + MethodHandle methodHandle = null; 2.26 + if (value instanceof ScriptFunction) { 2.27 + func = (ScriptFunction)value; 2.28 + methodHandle = getCallMethodHandle(func, desc.getMethodType(), name); 2.29 + } 2.30 2.31 if (methodHandle != null) { 2.32 if (scopeAccess && func.isStrict()) {
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8020223.js Fri Jul 12 15:27:16 2013 +0530 3.3 @@ -0,0 +1,71 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, 2013, 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-8020223: ClassCastException: String can not be casted to ScriptFunction 3.29 + * 3.30 + * @test 3.31 + * @run 3.32 + */ 3.33 + 3.34 +__noSuchMethod__ = ""; 3.35 + 3.36 +try { 3.37 + foo(); 3.38 + fail("Must have thrown exception"); 3.39 +} catch (e) { 3.40 + if (! (e instanceof TypeError)) { 3.41 + fail("TypeError expected, got " + e); 3.42 + } 3.43 +} 3.44 + 3.45 +__noSuchProperty__ = 23; 3.46 + 3.47 +try { 3.48 + foo; 3.49 + fail("Must have thrown exception"); 3.50 +} catch (e) { 3.51 + if (! (e instanceof ReferenceError)) { 3.52 + fail("ReferenceError expected, got " + e); 3.53 + } 3.54 +} 3.55 + 3.56 +var obj = new JSAdapter() { 3.57 + __get__: 332, 3.58 + __call__: "hello" 3.59 +} 3.60 + 3.61 +try { 3.62 + obj.foo; // should just be undefined 3.63 +} catch (e) { 3.64 + fail("unexpected error : " + e); 3.65 +} 3.66 + 3.67 +try { 3.68 + obj.foo(); 3.69 + fail("Must have thrown exception"); 3.70 +} catch(e) { 3.71 + if (! (e instanceof TypeError)) { 3.72 + fail("TypeError expected, got " + e); 3.73 + } 3.74 +}