8020223: ClassCastException: String can not be casted to ScriptFunction

Reviewed-by: attila, lagergren
This commit is contained in:
Athijegannathan Sundararajan 2013-07-12 15:27:16 +05:30
parent 4972fea316
commit eaed291ba6
3 changed files with 104 additions and 17 deletions

View File

@ -622,12 +622,15 @@ public final class NativeJSAdapter extends ScriptObject {
case "getMethod": case "getMethod":
final FindProperty find = adaptee.findProperty(__call__, true); final FindProperty find = adaptee.findProperty(__call__, true);
if (find != null) { if (find != null) {
final ScriptFunctionImpl func = (ScriptFunctionImpl)getObjectValue(find); final Object value = 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 if (value instanceof ScriptFunction) {
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null)); 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)); throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
default: default:
@ -687,16 +690,19 @@ public final class NativeJSAdapter extends ScriptObject {
final MethodType type = desc.getMethodType(); final MethodType type = desc.getMethodType();
if (findData != null) { if (findData != null) {
final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : 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); useName ? name : null);
if (methodHandle != null) { if (methodHandle != null) {
return new GuardedInvocation( return new GuardedInvocation(
methodHandle, methodHandle,
adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func)); testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
} }
}
} }
switch (hook) { switch (hook) {

View File

@ -1978,7 +1978,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return noSuchProperty(desc, request); 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; final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
// TODO: It'd be awesome if we could bind "name" without binding "this". // TODO: It'd be awesome if we could bind "name" without binding "this".
return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class, return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class,
@ -1998,8 +2003,13 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
if (find != null) { if (find != null) {
final ScriptFunction func = (ScriptFunction)getObjectValue(find); final Object value = getObjectValue(find);
MethodHandle methodHandle = getCallMethodHandle(func, desc.getMethodType(), name); ScriptFunction func = null;
MethodHandle methodHandle = null;
if (value instanceof ScriptFunction) {
func = (ScriptFunction)value;
methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
}
if (methodHandle != null) { if (methodHandle != null) {
if (scopeAccess && func.isStrict()) { if (scopeAccess && func.isStrict()) {

View File

@ -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);
}
}