# HG changeset patch # User sundar # Date 1438692534 -19800 # Node ID 8023426b93ab67e5229065e2c9b9457b2c011550 # Parent eeea9adfd1e3d075ef82148c00a4847a1aab4d26 8073733: TypeError messages with "call" and "new" could be improved Reviewed-by: attila, mhaupt diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Aug 04 18:18:54 2015 +0530 @@ -1480,7 +1480,7 @@ } @Override void consumeStack() { - dynamicCall(2 + argsCount, flags); + dynamicCall(2 + argsCount, flags, ident.getName()); } }.emit(); } @@ -1538,7 +1538,7 @@ @Override void consumeStack() { // Ordinary call - dynamicCall(2 + argsCount, flags); + dynamicCall(2 + argsCount, flags, "eval"); method._goto(eval_done); method.label(invoke_direct_eval); @@ -1610,7 +1610,7 @@ } @Override void consumeStack() { - dynamicCall(2 + argCount, flags); + dynamicCall(2 + argCount, flags, node.getProperty()); } }.emit(); @@ -1637,7 +1637,7 @@ void consumeStack() { final int flags = getCallSiteFlags(); //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType(); - dynamicCall(2 + argsCount, flags); + dynamicCall(2 + argsCount, flags, origCallee.getName()); } }.emit(); return false; @@ -1667,7 +1667,7 @@ @Override void consumeStack() { final int flags = getCallSiteFlags(); - dynamicCall(2 + argsCount, flags); + dynamicCall(2 + argsCount, flags, null); } }.emit(); return false; @@ -1687,7 +1687,7 @@ @Override void consumeStack() { final int flags = getCallSiteFlags() | CALLSITE_SCOPE; - dynamicCall(2 + argsCount, flags); + dynamicCall(2 + argsCount, flags, null); } }.emit(); return false; @@ -3707,10 +3707,12 @@ final CallNode callNode = (CallNode)unaryNode.getExpression(); final List args = callNode.getArgs(); + final Expression func = callNode.getFunction(); // Load function reference. - loadExpressionAsObject(callNode.getFunction()); // must detect type error - - method.dynamicNew(1 + loadArgs(args), getCallSiteFlags()); + loadExpressionAsObject(func); // must detect type error + + method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), + func instanceof IdentNode? ((IdentNode)func).getName() : null); } private void loadNOT(final UnaryNode unaryNode) { @@ -4818,11 +4820,11 @@ return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod); } - MethodEmitter dynamicCall(final int argCount, final int flags) { + MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) { if (isOptimistic) { - return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags)); - } - return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags)); + return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg); + } + return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg); } int getOptimisticFlags(final int flags) { diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Tue Aug 04 18:18:54 2015 +0530 @@ -2132,10 +2132,25 @@ * @return the method emitter */ MethodEmitter dynamicNew(final int argCount, final int flags) { + return dynamicNew(argCount, flags, null); + } + + /** + * Generate a dynamic new + * + * @param argCount number of arguments + * @param flags callsite flags + * @param msg additional message to be used when reporting error + * + * @return the method emitter + */ + MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) { assert !isOptimistic(flags); debug("dynamic_new", "argcount=", argCount); final String signature = getDynamicSignature(Type.OBJECT, argCount); - method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn( + msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new", + signature, LINKERBOOTSTRAP, flags); pushType(Type.OBJECT); //TODO fix result type return this; } @@ -2150,10 +2165,26 @@ * @return the method emitter */ MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) { + return dynamicCall(returnType, argCount, flags, null); + } + + /** + * Generate a dynamic call + * + * @param returnType return type + * @param argCount number of arguments + * @param flags callsite flags + * @param msg additional message to be used when reporting error + * + * @return the method emitter + */ + MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) { debug("dynamic_call", "args=", argCount, "returnType=", returnType); final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target) debug(" signature", signature); - method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn( + msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call", + signature, LINKERBOOTSTRAP, flags); pushType(returnType); return this; diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SharedScopeCall.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SharedScopeCall.java Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SharedScopeCall.java Tue Aug 04 18:18:54 2015 +0530 @@ -169,7 +169,7 @@ slot += type.getSlots(); } // Shared scope calls disabled in optimistic world. TODO is this right? - method.dynamicCall(returnType, 2 + paramTypes.length, flags); + method.dynamicCall(returnType, 2 + paramTypes.length, flags, symbol.getName()); } method._return(returnType); diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Tue Aug 04 18:18:54 2015 +0530 @@ -96,8 +96,12 @@ switch (operator) { case "new": - case "call": - throw lookupTypeError("cant.call.undefined", desc); + case "call": { + final String name = desc.getNameTokenCount() > 2? desc.getNameToken(2) : null; + final String msg = name != null? "cant.call.undefined.arg" : "cant.call.undefined"; + throw typeError(msg, name); + } + case "callMethod": throw lookupTypeError("cant.read.property.of.undefined", desc); // NOTE: we support getElem and setItem as JavaScript doesn't distinguish items from properties. Nashorn itself @@ -125,7 +129,8 @@ } private static ECMAException lookupTypeError(final String msg, final CallSiteDescriptor desc) { - return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null); + final String name = desc.getNameToken(2); + return typeError(msg, name != null && !name.isEmpty()? name : null); } private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class); diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Tue Aug 04 18:18:54 2015 +0530 @@ -150,7 +150,7 @@ public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name, final MethodType methodType, final int flags) { final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name); - assert tokenizedName.length == 2 || tokenizedName.length == 3; + assert tokenizedName.length >= 2; assert "dyn".equals(tokenizedName[0]); assert tokenizedName[1] != null; // TODO: see if we can move mangling/unmangling into Dynalink diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Tue Aug 04 18:18:54 2015 +0530 @@ -87,6 +87,7 @@ # 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 diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/test/script/basic/JDK-8026016.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8026016.js.EXPECTED Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8026016.js.EXPECTED Tue Aug 04 18:18:54 2015 +0530 @@ -1,182 +1,182 @@ -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -TypeError: Cannot call undefined -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such method _,0 -no such method _,1 -no such method _,2 -no such method _,3 -no such method _,4 -no such method _,5 -no such method _,6 -no such method _,7 -no such method _,8 -no such method _,9 -no such method _,10 -no such method _,11 -no such method _,12 -no such method _,13 -no such method _,14 -no such method _,15 -no such method _,16 -no such method _,17 -no such method _,18 -no such method _,19 -no such method _,20 -no such method _,21 -no such method _,22 -no such method _,23 -no such method _,24 -no such method _,25 -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -TypeError: Cannot call undefined -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ -no such property _ +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +TypeError: Cannot call "_" that has undefined value +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such method _,0 +no such method _,1 +no such method _,2 +no such method _,3 +no such method _,4 +no such method _,5 +no such method _,6 +no such method _,7 +no such method _,8 +no such method _,9 +no such method _,10 +no such method _,11 +no such method _,12 +no such method _,13 +no such method _,14 +no such method _,15 +no such method _,16 +no such method _,17 +no such method _,18 +no such method _,19 +no such method _,20 +no such method _,21 +no such method _,22 +no such method _,23 +no such method _,24 +no such method _,25 +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +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 +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ +no such property _ diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/test/script/basic/JDK-8073733.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8073733.js Tue Aug 04 18:18:54 2015 +0530 @@ -0,0 +1,49 @@ +/* + * 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-8073733: TypeError messages with "call" and "new" could be improved + * + * @test + * @run + */ + +var func = undefined; +try { + func(); +} catch (e) { + print(e); +} + +var obj = {}; +try { + obj.foo(); +} catch (e) { + print(e); +} + +try { + new func(); +} catch (e) { + print(e); +} diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/test/script/basic/JDK-8073733.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8073733.js.EXPECTED Tue Aug 04 18:18:54 2015 +0530 @@ -0,0 +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 diff -r eeea9adfd1e3 -r 8023426b93ab nashorn/test/script/basic/errors.js.EXPECTED --- a/nashorn/test/script/basic/errors.js.EXPECTED Wed Jul 05 20:44:11 2017 +0200 +++ b/nashorn/test/script/basic/errors.js.EXPECTED Tue Aug 04 18:18:54 2015 +0530 @@ -1,31 +1,31 @@ -Error is a function -EvalError is a function -RangeError is a function -ReferenceError is a function -SyntaxError is a function -TypeError is a function -URIError is a function -Error.arity 1 -EvalError.arity 1 -RangeError.arity 1 -ReferenceError.arity 1 -SyntaxError.arity 1 -TypeError.arity 1 -URIError.arity 1 -true -my error -Error -thrown @ 49 -true -ReferenceError -"foo" is not defined -true -TypeError -Cannot call undefined -Error -EvalError -RangeError -ReferenceError -SyntaxError -TypeError -URIError +Error is a function +EvalError is a function +RangeError is a function +ReferenceError is a function +SyntaxError is a function +TypeError is a function +URIError is a function +Error.arity 1 +EvalError.arity 1 +RangeError.arity 1 +ReferenceError.arity 1 +SyntaxError.arity 1 +TypeError.arity 1 +URIError.arity 1 +true +my error +Error +thrown @ 49 +true +ReferenceError +"foo" is not defined +true +TypeError +Cannot call "foo_method" that has undefined value +Error +EvalError +RangeError +ReferenceError +SyntaxError +TypeError +URIError