--- old/samples/dynalink/underscore_linker.js 2016-11-02 17:58:57.203292300 +0530 +++ new/samples/dynalink/underscore_linker.js 2016-11-02 17:58:55.921259700 +0530 @@ -46,5 +46,6 @@ // but make sure classpath points to the pluggable linker jar! `jjs -cp underscore_linker.jar underscore.js` +print($ERR) print($OUT) --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java 2016-11-02 17:59:09.110668200 +0530 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java 2016-11-02 17:59:07.340566900 +0530 @@ -542,4 +542,9 @@ public CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) { return get(getLookupPrivileged(), getOperation(), newMethodType, flags); } + + @Override + protected CallSiteDescriptor changeOperationInternal(final Operation newOperation) { + return get(getLookupPrivileged(), newOperation, getMethodType(), flags); + } } --- old/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter 2016-11-02 17:59:17.933172800 +0530 +++ new/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter 2016-11-02 17:59:16.514091600 +0530 @@ -1,2 +1,3 @@ jdk.dynalink.test.UntrustedGuardingDynamicLinkerExporter jdk.dynalink.test.TrustedGuardingDynamicLinkerExporter +jdk.dynalink.test.TrustedUnderscoreNameLinkerExporter --- old/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java 2016-11-02 17:59:30.111869400 +0530 +++ new/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java 2016-11-02 17:59:28.643785400 +0530 @@ -104,11 +104,11 @@ @Test public void testVarArgs() throws ScriptException { // Sole NativeArray in vararg position becomes vararg array itself - runTest("assertVarArg_42_17", "[42, 17]"); + runTest("assertVarArgWith42And17", "[42, 17]"); // NativeArray in vararg position becomes an argument if there are more arguments - runTest("assertVarArg_array_17", "[42], 18"); + runTest("assertVarArgArray7", "[42], 18"); // Only NativeArray is converted to vararg array, other objects (e.g. a function) aren't - runTest("assertVarArg_function", "function() { return 'Hello' }"); + runTest("assertVarArgFunction", "function() { return 'Hello' }"); } private static void runTest(final String testMethodName, final String argument) throws ScriptException { @@ -209,20 +209,20 @@ assertEquals(Arrays.asList("apple", "orange"), array[1]); } - public static void assertVarArg_42_17(final Object... args) { + public static void assertVarArgWith42And17(final Object... args) { assertEquals(2, args.length); assertEquals(42, ((Number)args[0]).intValue()); assertEquals(17, ((Number)args[1]).intValue()); } - public static void assertVarArg_array_17(final Object... args) throws ScriptException { + public static void assertVarArgArray7(final Object... args) throws ScriptException { assertEquals(2, args.length); e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]); assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42")); assertEquals(18, ((Number)args[1]).intValue()); } - public static void assertVarArg_function(final Object... args) throws ScriptException { + public static void assertVarArgFunction(final Object... args) throws ScriptException { assertEquals(1, args.length); e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]); assertEquals("Hello", e.eval("fn()")); --- /dev/null 2016-11-02 17:59:39.000000000 +0530 +++ new/test/src/jdk/dynalink/test/TrustedUnderscoreNameLinkerExporter.java 2016-11-02 17:59:37.856312300 +0530 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.dynalink.test; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.NamespaceOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardNamespace; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.SimpleLinkRequest; + +/** + * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). + * This linker translater underscore_separated method names to CamelCase names + * used in Java APIs. + */ +public final class TrustedUnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter { + private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)"); + + // translate underscore_separated name as a CamelCase name + private static String translateToCamelCase(final String name) { + final Matcher m = UNDERSCORE_NAME.matcher(name); + final StringBuilder buf = new StringBuilder(); + while (m.find()) { + m.appendReplacement(buf, m.group(1).toUpperCase()); + } + m.appendTail(buf); + return buf.toString(); + } + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add(new GuardingDynamicLinker() { + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, + final LinkerServices linkerServices) throws Exception { + final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + final Operation op = desc.getOperation(); + final Object name = NamedOperation.getName(op); + final Operation namespaceOp = NamedOperation.getBaseOperation(op); + // is this a named GET_METHOD? + final boolean isGetMethod = + NamespaceOperation.getBaseOperation(namespaceOp) == StandardOperation.GET + && StandardNamespace.findFirst(namespaceOp) == StandardNamespace.METHOD; + if (isGetMethod && name instanceof String) { + final String str = (String)name; + if (str.indexOf('_') == -1) { + return null; + } + + final String nameStr = translateToCamelCase(str); + // create a new call descriptor to use translated name + final CallSiteDescriptor newDesc = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public CallSiteDescriptor run() { + return desc.changeOperation(((NamedOperation)op).changeName(nameStr)); + } + }); + // create a new Link request to link the call site with translated name + final LinkRequest newRequest = request.replaceArguments(newDesc, request.getArguments()); + // return guarded invocation linking the translated request + return linkerServices.getGuardedInvocation(newRequest); + } + + return null; + } + }); + return linkers; + } +} --- /dev/null 2016-11-02 17:59:46.000000000 +0530 +++ new/test/src/jdk/nashorn/api/scripting/test/JDK_8169050_Test.java 2016-11-02 17:59:44.901715300 +0530 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package jdk.nashorn.api.scripting.test; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * @bug 8169050 + * @summary underscore_linker.js sample fails after dynalink changes for JDK-8168005 + */ +public class JDK_8169050_Test { + private ScriptEngine engine; + + @BeforeClass + public void setupTest() { + engine = new ScriptEngineManager().getEngineByName("js"); + } + + @Test + public void testUndersoreName() throws ScriptException { + engine.eval("var S = java.util.stream.Stream, v = 0;"); + // The underscore name 'for_each' exercises pluggable dynalink linker + engine.eval("S.of(4, 5, 9).for_each(function(x) { v += x })"); + assertEquals(18, ((Number)engine.get("v")).intValue()); + } +}