--- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java 2016-02-29 10:05:05.753145400 +0530 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java 2016-02-29 10:05:05.373144800 +0530 @@ -33,6 +33,9 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.DynamicLinker; import jdk.dynalink.DynamicLinkerFactory; @@ -70,6 +73,7 @@ private static final BeansLinker beansLinker = new BeansLinker(Bootstrap::createMissingMemberHandler); private static final GuardingDynamicLinker[] prioritizedLinkers; private static final GuardingDynamicLinker[] fallbackLinkers; + static { final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker(beansLinker); prioritizedLinkers = new GuardingDynamicLinker[] { @@ -90,6 +94,19 @@ } /** + * Returns a list of exposed nashorn dynalink linkers. + * + * @return a list of exposed nashorn dynalink linkers. + */ + public static List getExposedLinkers() { + // we have to create BeansLinker without nashorn specific missing member handler! + // Or else, we'd return values such as 'undefined' to the external world! + final NashornBeansLinker nbl = new NashornBeansLinker(new BeansLinker()); + final JSObjectLinker linker = new JSObjectLinker(nbl); + return Collections.singletonList(linker); + } + + /** * Creates a Nashorn dynamic linker with the given app class loader. * @param appLoader the app class loader. It will be used to discover * additional language runtime linkers (if any). --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java 2016-02-29 10:05:08.203148800 +0530 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java 2016-02-29 10:05:07.763148200 +0530 @@ -71,6 +71,9 @@ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final Object self = request.getReceiver(); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + if (self == null || !canLinkTypeStatic(self.getClass())) { + return null; + } GuardedInvocation inv; if (self instanceof JSObject) { @@ -82,7 +85,7 @@ inv = new GuardedInvocation(beanInv.getInvocation(), NashornGuards.combineGuards(beanInv.getGuard(), NashornGuards.getNotJSObjectGuard())); } else { - throw new AssertionError(); // Should never reach here. + throw new AssertionError("got instanceof: " + self.getClass()); // Should never reach here. } return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); --- old/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java 2016-02-29 10:05:10.413151900 +0530 +++ new/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java 2016-02-29 10:05:10.033151400 +0530 @@ -30,10 +30,13 @@ import java.lang.invoke.MethodType; import java.util.List; import java.util.ServiceConfigurationError; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.DynamicLinker; import jdk.dynalink.DynamicLinkerFactory; import jdk.dynalink.NoSuchDynamicMethodException; +import jdk.dynalink.NamedOperation; import jdk.dynalink.Operation; import jdk.dynalink.StandardOperation; import jdk.dynalink.linker.GuardingDynamicLinker; @@ -41,6 +44,7 @@ import jdk.dynalink.linker.LinkerServices; import jdk.dynalink.support.SimpleRelinkableCallSite; import jdk.dynalink.linker.GuardedInvocation; +import jdk.nashorn.api.scripting.AbstractJSObject; import org.testng.Assert; import org.testng.annotations.Test; @@ -254,4 +258,44 @@ Assert.assertTrue(reachedAutoLinker); } + + @Test + public void nashornExportedLinkersTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(false); + final DynamicLinker linker = factory.createLinker(); + + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final NamedOperation op = new NamedOperation(StandardOperation.GET_PROPERTY, "foo"); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), op, mt))); + final boolean[] reachedGetMember = new boolean[1]; + // check that the nashorn exported linker can be used for user defined JSObject + Object obj = new AbstractJSObject() { + @Override + public Object getMember(String name) { + reachedGetMember[0] = true; + return name.equals("foo")? "bar" : ""; + } + }; + + Object value = null; + try { + value = cs.getTarget().invoke(obj); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(reachedGetMember[0]); + Assert.assertEquals(value, "bar"); + + // check that the nashorn exported linker can be used for ScriptObjectMirror + final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); + try { + obj = engine.eval("({ foo: 'hello' })"); + value = cs.getTarget().invoke(obj); + } catch (Throwable th) { + throw new RuntimeException(th); + } + Assert.assertEquals(value, "hello"); + } } --- /dev/null 2016-02-29 10:05:12.000000000 +0530 +++ new/src/jdk.scripting.nashorn/share/classes/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter 2016-02-29 10:05:12.223154400 +0530 @@ -0,0 +1 @@ +jdk.nashorn.api.linker.NashornLinkerExporter --- /dev/null 2016-02-29 10:05:14.000000000 +0530 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/linker/NashornLinkerExporter.java 2016-02-29 10:05:13.923156800 +0530 @@ -0,0 +1,60 @@ +/* + * 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.nashorn.api.linker; + +import java.util.List; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.nashorn.internal.runtime.linker.Bootstrap; + +/** + * This linker exporter is a service provider that exports Nashorn Dynalink + * linkers to external users. Other languague runtimes that use Dynalink + * can use the linkers exported by this provider to support tight integration + * of Nashorn objects. + */ +public final class NashornLinkerExporter extends GuardingDynamicLinkerExporter { + /** + * The default constructor. + */ + public NashornLinkerExporter() {} + + /** + * Returns a list of exported nashorn specific linkers. + * + * @return list of exported nashorn specific linkers + */ + @Override + public List get() { + return Bootstrap.getExposedLinkers(); + } +}