8133119: Error message associated with TypeError for call and new should include stringified Node

Reviewed-by: attila, mhaupt
This commit is contained in:
Athijegannathan Sundararajan 2015-08-06 21:50:42 +05:30
parent b2ad94c8e5
commit 8d8c82f34e
17 changed files with 230 additions and 84 deletions

View File

@ -1610,7 +1610,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
void consumeStack() {
dynamicCall(2 + argCount, flags, node.getProperty());
dynamicCall(2 + argCount, flags, node.toString(false));
}
}.emit();
@ -1635,9 +1635,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
void consumeStack() {
final int flags = getCallSiteFlags();
//assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
dynamicCall(2 + argsCount, flags, origCallee.getName());
dynamicCall(2 + argsCount, getCallSiteFlags(), origCallee.getName());
}
}.emit();
return false;
@ -1666,8 +1664,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
void consumeStack() {
final int flags = getCallSiteFlags();
dynamicCall(2 + argsCount, flags, null);
dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
}
}.emit();
return false;
@ -1687,7 +1684,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
void consumeStack() {
final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
dynamicCall(2 + argsCount, flags, null);
dynamicCall(2 + argsCount, flags, node.toString(false));
}
}.emit();
return false;
@ -3711,8 +3708,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// Load function reference.
loadExpressionAsObject(func); // must detect type error
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(),
func instanceof IdentNode? ((IdentNode)func).getName() : null);
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
}
private void loadNOT(final UnaryNode unaryNode) {

View File

@ -141,9 +141,17 @@ public abstract class Node implements Cloneable, Serializable {
public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
@Override
public String toString() {
public final String toString() {
return toString(true);
}
/*
* Return String representation of this Node.
* @param includeTypeInfo include type information or not
*/
public final String toString(final boolean includeTypeInfo) {
final StringBuilder sb = new StringBuilder();
toString(sb);
toString(sb, includeTypeInfo);
return sb.toString();
}

View File

@ -1859,7 +1859,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return notAFunction();
return notAFunction(desc);
}
/**
@ -1872,11 +1872,11 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return notAFunction();
return notAFunction(desc);
}
private GuardedInvocation notAFunction() {
throw typeError("not.a.function", ScriptRuntime.safeToString(this));
private GuardedInvocation notAFunction(final CallSiteDescriptor desc) {
throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, this));
}
/**

View File

@ -97,8 +97,8 @@ public final class Undefined extends DefaultPropertyAccess {
switch (operator) {
case "new":
case "call": {
final String name = desc.getNameTokenCount() > 2? desc.getNameToken(2) : null;
final String msg = name != null? "cant.call.undefined.arg" : "cant.call.undefined";
final String name = NashornCallSiteDescriptor.getFunctionDescription(desc);
final String msg = name != null? "not.a.function" : "cant.call.undefined";
throw typeError(msg, name);
}

View File

@ -27,6 +27,8 @@ package jdk.nashorn.internal.runtime.linker;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
@ -92,7 +94,7 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
if(BeansLinker.isDynamicMethod(self)) {
throw typeError("method.not.constructor", ScriptRuntime.safeToString(self));
}
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
case "call":
if(BeansLinker.isDynamicConstructor(self)) {
throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
@ -100,10 +102,12 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
if(BeansLinker.isDynamicMethod(self)) {
throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
}
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
case "callMethod":
case "getMethod":
throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
case "getMethod":
// evaluate to undefined, later on Undefined will take care of throwing TypeError
return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc);
case "getProp":
case "getElem":
if(NashornCallSiteDescriptor.isOptimistic(desc)) {

View File

@ -34,6 +34,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.ir.debug.NashornTextifier;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
* Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@ -247,6 +248,54 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
return operand;
}
/**
* If this is a dyn:call or dyn:new, this returns function description from callsite.
* Caller has to make sure this is a dyn:call or dyn:new call site.
*
* @return function description if available (or null)
*/
public String getFunctionDescription() {
assert getFirstOperator().equals("call") || getFirstOperator().equals("new");
return getNameTokenCount() > 2? getNameToken(2) : null;
}
/**
* If this is a dyn:call or dyn:new, this returns function description from callsite.
* Caller has to make sure this is a dyn:call or dyn:new call site.
*
* @param desc call site descriptor
* @return function description if available (or null)
*/
public static String getFunctionDescription(final CallSiteDescriptor desc) {
return desc instanceof NashornCallSiteDescriptor ?
((NashornCallSiteDescriptor)desc).getFunctionDescription() : null;
}
/**
* Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
*
* @param obj object on which dyn:call or dyn:new is used
* @return error message
*/
public String getFunctionErrorMessage(final Object obj) {
final String funcDesc = getFunctionDescription();
return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
}
/**
* Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
*
* @param desc call site descriptor
* @param obj object on which dyn:call or dyn:new is used
* @return error message
*/
public static String getFunctionErrorMessage(final CallSiteDescriptor desc, final Object obj) {
return desc instanceof NashornCallSiteDescriptor ?
((NashornCallSiteDescriptor)desc).getFunctionErrorMessage(obj) :
ScriptRuntime.safeToString(obj);
}
/**
* Returns the Nashorn-specific flags for this call site descriptor.
* @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a

View File

@ -78,6 +78,7 @@ type.error.not.a.number={0} is not a Number
type.error.not.a.regexp={0} is not a RegExp
type.error.not.a.string={0} is not a String
type.error.not.a.function={0} is not a function
type.error.not.a.function.value={0}, which has value {1}, is not a function
type.error.not.a.constructor={0} is not a constructor function
type.error.not.a.file={0} is not a File
type.error.not.a.numeric.array={0} is not a numeric array
@ -87,7 +88,6 @@ type.error.no.reflection.with.classfilter=Java reflection not supported when cla
# operations not permitted on undefined
type.error.cant.call.undefined=Cannot call undefined
type.error.cant.call.undefined.arg=Cannot call "{0}" that has undefined value
type.error.cant.read.property.of.undefined=Cannot read property "{0}" from undefined
type.error.cant.set.property.of.undefined=Cannot set property "{0}" of undefined
type.error.cant.delete.property.of.undefined=Cannot delete property "{0}" of undefined

View File

@ -1,55 +1,55 @@
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
no such property _
no such property _
no such property _
@ -128,32 +128,32 @@ no such property _
no such property _
no such property _
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
TypeError: o._ is not a function
no such property _
no such property _
no such property _

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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

View File

@ -1,3 +1,3 @@
TypeError: Cannot call "func" that has undefined value
TypeError: Cannot call "foo" that has undefined value
TypeError: Cannot call "func" that has undefined value
TypeError: func is not a function
TypeError: obj.foo is not a function
TypeError: func is not a function

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2015, 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-8133119: Error message associated with TypeError for call and new should include stringified Node
*
* @test
* @run
*/
var obj = {}
try {
obj.func();
} catch (e) {
print(e);
}
var arr = [33];
try {
arr[0].func();
} catch (e) {
print(e);
}
try {
new obj.func();
} catch (e) {
print(e);
}
try {
new arr[0].func();
} catch (e) {
print(e);
}
obj.foo = {}
try {
new obj.foo();
} catch (e) {
print(e);
}
try {
obj.foo();
} catch (e) {
print(e);
}
var v = new java.util.Vector();
try {
v();
} catch (e) {
print(e);
}
try {
new v();
} catch (e) {
print(e);
}

View File

@ -0,0 +1,8 @@
TypeError: obj.func is not a function
TypeError: arr[0].func is not a function
TypeError: obj.func is not a function
TypeError: arr[0].func is not a function
TypeError: obj.foo is not a function
TypeError: obj.foo is not a function
TypeError: v is not a function
TypeError: v is not a function

View File

@ -1,3 +1,3 @@
TypeError: [RegExp /a|b/g] is not a function
TypeError: [String hello] is not a function
TypeError: [object Object] is not a function
TypeError: RegExp("a|b", "g") is not a function
TypeError: new String("hello") is not a function
TypeError: new Object() is not a function

View File

@ -21,7 +21,7 @@ ReferenceError
"foo" is not defined
true
TypeError
Cannot call "foo_method" that has undefined value
Object.foo_method is not a function
Error
EvalError
RangeError