Fri, 13 May 2016 14:30:54 +0200
8156896: Script stack trace should display function names
Reviewed-by: attila, sundar
1.1 --- a/src/jdk/nashorn/api/scripting/NashornException.java Wed May 25 21:10:36 2016 +0530 1.2 +++ b/src/jdk/nashorn/api/scripting/NashornException.java Fri May 13 14:30:54 2016 +0200 1.3 @@ -175,10 +175,8 @@ 1.4 String methodName = st.getMethodName(); 1.5 if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { 1.6 methodName = "<program>"; 1.7 - } 1.8 - 1.9 - if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) { 1.10 - methodName = "<anonymous>"; 1.11 + } else { 1.12 + methodName = stripMethodName(methodName); 1.13 } 1.14 1.15 filtered.add(new StackTraceElement(className, methodName, 1.16 @@ -188,6 +186,22 @@ 1.17 return filtered.toArray(new StackTraceElement[filtered.size()]); 1.18 } 1.19 1.20 + private static String stripMethodName(final String methodName) { 1.21 + String name = methodName; 1.22 + 1.23 + final int nestedSeparator = name.lastIndexOf(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName()); 1.24 + if (nestedSeparator >= 0) { 1.25 + name = name.substring(nestedSeparator + 1); 1.26 + } 1.27 + 1.28 + final int idSeparator = name.indexOf(CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName()); 1.29 + if (idSeparator >= 0) { 1.30 + name = name.substring(0, idSeparator); 1.31 + } 1.32 + 1.33 + return name.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName()) ? "<anonymous>" : name; 1.34 + } 1.35 + 1.36 /** 1.37 * Return a formatted script stack trace string with frames information separated by '\n' 1.38 *
2.1 --- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java Wed May 25 21:10:36 2016 +0530 2.2 +++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java Fri May 13 14:30:54 2016 +0200 2.3 @@ -78,6 +78,12 @@ 2.4 /** function prefix for anonymous functions */ 2.5 ANON_FUNCTION_PREFIX("L:"), 2.6 2.7 + /** separator for method names of nested functions */ 2.8 + NESTED_FUNCTION_SEPARATOR("#"), 2.9 + 2.10 + /** separator for making method names unique by appending numeric ids */ 2.11 + ID_FUNCTION_SEPARATOR("-"), 2.12 + 2.13 /** method name for Java method that is the program entry point */ 2.14 PROGRAM(":program"), 2.15
3.1 --- a/src/jdk/nashorn/internal/codegen/Namespace.java Wed May 25 21:10:36 2016 +0530 3.2 +++ b/src/jdk/nashorn/internal/codegen/Namespace.java Fri May 13 14:30:54 2016 +0200 3.3 @@ -68,7 +68,7 @@ 3.4 } 3.5 3.6 /** 3.7 - * Create a uniqueName name in the namespace in the form base$n where n varies. 3.8 + * Create a uniqueName name in the namespace in the form base-n where n varies. 3.9 * Also truncates very long names that would otherwise break ASM. 3.10 * 3.11 * @param base Base of name. Base will be returned if uniqueName. 3.12 @@ -83,7 +83,7 @@ 3.13 if (counter != null) { 3.14 final int count = counter + 1; 3.15 namespaceDirectory.put(truncatedBase, count); 3.16 - return truncatedBase + '-' + count; 3.17 + return truncatedBase + CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName() + count; 3.18 } 3.19 } 3.20
4.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Wed May 25 21:10:36 2016 +0530 4.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Fri May 13 14:30:54 2016 +0200 4.3 @@ -459,7 +459,7 @@ 4.4 4.5 final FunctionNode parentFunction = lc.getCurrentFunction(); 4.6 if (parentFunction != null && !parentFunction.isProgram()) { 4.7 - sb.append(parentFunction.getName()).append('$'); 4.8 + sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName()); 4.9 } 4.10 4.11 assert ident.getName() != null;
5.1 --- a/test/script/basic/JDK-8025515.js Wed May 25 21:10:36 2016 +0530 5.2 +++ b/test/script/basic/JDK-8025515.js Fri May 13 14:30:54 2016 +0200 5.3 @@ -61,8 +61,8 @@ 5.4 var f = (function() { 5.5 return function() { a.b.c; }; 5.6 })(); 5.7 -testMethodName(f, "f$L:62"); 5.8 +testMethodName(f, "f#L:62"); 5.9 5.10 testMethodName((function() { 5.11 return function() { return a.b.c; }; 5.12 -})(), "L:66$L:67"); 5.13 +})(), "L:66#L:67");
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/script/basic/JDK-8156896.js Fri May 13 14:30:54 2016 +0200 6.3 @@ -0,0 +1,59 @@ 6.4 +/* 6.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/** 6.28 + * JDK-8156896: Script stack trace should display function names 6.29 + * 6.30 + * @test 6.31 + * @run 6.32 + */ 6.33 + 6.34 +function checkNamedFunction(stack) { 6.35 + Assert.assertTrue(stack.indexOf("Error\n\tat bar (") === 0); 6.36 +} 6.37 + 6.38 +function checkAnonymousFunction(stack) { 6.39 + Assert.assertTrue(stack.indexOf("Error\n\tat <anonymous> (") === 0); 6.40 +} 6.41 + 6.42 +// Named functions 6.43 +function bar() { try { throw new Error(); } catch(e) { return e.stack; } } 6.44 +checkNamedFunction(bar()); 6.45 + 6.46 +bar = function() { try { throw new Error(); } catch(e) { return e.stack; } }; 6.47 +checkNamedFunction(bar()); 6.48 + 6.49 +f = (function() {return function bar() { try { throw new Error(); } catch(e) { return e.stack; } } })(); 6.50 +checkNamedFunction(f()); 6.51 + 6.52 +f = new Function("return function bar() { try { throw new Error(); } catch(e) { return e.stack; } }")(); 6.53 +checkNamedFunction(f()); 6.54 + 6.55 +// Anonymous functions 6.56 +checkAnonymousFunction((function() { try { throw new Error(); } catch(e) { return e.stack; } })()); 6.57 + 6.58 +f = (function() {return function() { try { throw new Error(); } catch(e) { return e.stack; } } })(); 6.59 +checkAnonymousFunction(f()); 6.60 + 6.61 +f = new Function("return function() { try { throw new Error(); } catch(e) { return e.stack; } }")(); 6.62 +checkAnonymousFunction(f());