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":
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 @@ public final class NativeJSAdapter extends ScriptObject {
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) {

View File

@ -1978,7 +1978,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
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 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
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()) {

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